gpt4 book ai didi

objective-c - 在 Objective-C 中初始化对象

转载 作者:行者123 更新时间:2023-12-04 18:19:15 26 4
gpt4 key购买 nike

我无法理解 Stephen Kochan 的“Objective-C 编程”一书中的以下内容 - 第 4 版。我希望你能帮助我理解它。

在第 10 章“初始化对象”一节中,Stephen 写道:

You should adhere to the following two strategies when writing initialisers.

It might be the case that you want to do something special whenever one of the objects in your class gets initialised. For example, that's the perfect place to create the objects that your class uses and references through one or more instance variables. A perfect example of that would be our Rectangle class; it would be reasonable to allocate the rectangle's XYPoint origin in the init method. To do so, we just have to override the inherited init method.

There's a standard 'template' that's used for overriding init, and it looks like this:


- (id) init
{
self = [super init];
if (self) {
// initialisation code here.
}

return self;
}

This method invokes the parent initialiser first. Executing the parent's initialiser ensures that any inherited instance variables are properly initialised.

You must assign the result of executing the parent's init method back to self because an initialiser has the right to change the location of the object in memory (meaning its reference will change).

If the parent's initialiser succeeds, the value returned will be non-nil, as tested by the if statement. As the comment indicates, inside the block that follows is where you can put your own custom code for your object. This will often involve allocating and initialising instance variables that are in your class.



好的,到目前为止,我已经理解了 Stephen Kochan 想要说的内容,但我完全被下一部分迷惑了。我希望你能帮忙。

If you class contains more than one initialiser, one of them should be your designated initialiser and all the other initialisation methods should use it. Typically, that is your most complex initialisation method (usually, one that takes the most arguments).



所以,我的第一个问题是:如果所有其他初始化方法在这种情况下都将使用一个特定的初始化方法,那么为什么还要使用“指定”初始化方法?

Stephen Kochan 继续说:

Creating a designated initialiser centralises your main initialisation code in a single method. Anyone subclassing your class can then override your designated initialiser to ensure that new instances are properly initialised.



你能举个例子吗?我不太确定我明白他在说什么。

斯蒂芬继续说:

Based on that discussion, your initialisation method initWith:over: for your Fraction class might look like this:


- (Fraction *) initWith:(int)n over:(int)d
{
self = [super init];

if (self) {
[self setTo: n over: d];
}

return self;
}

Following the initialisation of super (and its success, as indicated by the return of a nonzero value) you use the setTo:over: method to set the numerator and denominator of your Fraction. As with other initialisation methods, you are expected to return the initialised object, which you do here.

Program 10.1 tests your new initWith:over: initialisation method.


#import "Fraction.h"

int main (int argc, char *argv[])
{
@autoreleasepool {
Fraction *a, *b;

a = [[Fraction alloc] initWith: 1 over: 3];
b = [[Fraction alloc] initWith: 3 over: 7];

[a print];
[b print];

}

return 0;
}

Output:
1/3
3/7



到目前为止,我已经理解了代码。以下部分我完全不明白:

To adhere to the rule stated earlier about a designated initialiser, you should also modify init in your Fraction class. That's particularly important if your class might be subclassed.

Here's what the init method could look like:


- (id)init
{
return [self initWith:0 over:0];
}

如果我们想要子类化,为什么这很重要?

Stephen Kochan 继续说道:

When your program begins execution, it sends the initialisation call method to all your classes. If you have a class and associated subclasses, the parent class gets the message first. This message is sent only once to each class, and it is guaranteed to be sent before any other messages are sent to the class. The purpose is for you to perform any class initialisation at that point. For example, you might want to initialise some static variables associated with that class at that time.



我也没有真正理解最后一部分。我希望你能提供帮助。

最佳答案

这是一大堆问题,很难回答。

So, my first question is: why have all the other initialisation methods if they're all going to use one particular one in this case the "designated" initialiser?



主要是为了方便您的来电。例如,假设您指定的初始化程序是 initWithX:y:width:height: ,但你发现自己到处写这样的东西:
[[MyRect alloc] initWithX:0 y:0 width:0 height:0]
[[MyRect alloc] initWithX:myPoint.x y:myPoint.y width:mySize.width height:mySize.height]

你可能想添加另外几个初始化器,所以你可以这样做:
[[MyRect alloc] initWithEmptyRect]
[[MyRect alloc] initWithPoint:myPoint size:mySize]

当然,它实际上从来没有必要,但出于同样的原因,它总是值得做的,而不是一遍又一遍地重复自己。

通过查看 Foundation/Cocoa 附带的各种类,您可以找到更实际的示例——它们中的许多具有许多不同的初始化程序,而且它们通常包含更多的工作,而不仅仅是调用 .x、.y、.width 和 .高度。例如,NSDictionary 有像 -initWithContentsOfURL: 这样的方法。 .理论上,您总是可以读取该 URL 的内容,将 plist 解析为一对 C 风格的对象和键数组,然后调用 -initWithObjects:forKeys:count: ,所以这实际上没有必要。但你更愿意做什么?

"Creating a designated initialiser centralises your main initialisation code in a single method. Anyone subclassing your class can then override your designated initialiser to ensure that new instances are properly initialised".

Could you give an example of this? I'm not quite sure I understood what he's saying.



假设有人创建了这个类:
@interface MySuperRect: MyRect
- (id)initWithX:x y:y width:width height:height;
@end

他不需要覆盖你所有的 init 方法,只需要这个。假设你这样做:
[[MySuperRect alloc] initWithEmptyRect]

因为 MySuperRect 没有实现 initWithEmptyRect,这将使用 MyRect 的实现,它只是调用指定的初始化器。但是 MySuperRect 已经实现了指定的初始化器。因此,将调用覆盖。

我认为这也回答了你的第三个问题。 (我认为这是第三个问题。)

对于您的第四个也是最后一个问题,您需要先解释一下您不理解的部分,然后才能有人帮助您。例如,您是否认为类只是一种(稍微)特殊的对象,并且通常了解对象初始化的工作原理,以及类初始化的特殊之处,但不明白为什么要在那里初始化静态变量?

关于objective-c - 在 Objective-C 中初始化对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11025015/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com