我为什么要调用self =

比方说,我创build我的类和它的init方法。 我为什么要调用并返回分配给自己的超类init值? 它涵盖了哪些情况?

我将不胜感激为什么我会需要它的cocoa超类和非cocoa。

你的意思是为什么

 self = [super init]; 

而不是

 [super init]; 

两个原因:

  1. 在初始化中,失败表示为返回零。 您需要知道超级对象的初始化是否失败。
  2. 超类可能会select用另一个对象replace+ alloc所返回的自我。 这很less见,但在class级集群中经常发生。

回应Michael的评论编辑:

我可以理解为什么我需要保存并返回[超级初始化]。 但是这只是惯例和好看让我们用自己作为一个临时variables来传递结果吗?

编号实例variables是相对于自指针访问的,所以在下面:

 -(id) init { self = [super init]; if (self != nil) { myBoolIvar = YES; // The above is an implicit version of self->myBoolIvar = YES; } return self; } 

自己显然已经指向了正确的内存块,即你将要返回的内存块。

另一点是,如果超级初始化返回不同的类实例,那么在该行之后的其余代码可能甚至没有意义,导致内存泄漏和崩溃,甚至没有谈论从该类实例化的对象。

这可能是一个问题。 如果我将子类NSNumber和[超级初始化]决定返回一个NSString(它可以 – 没有什么可以阻止它),这显然是一场灾难。 无论从-init提供的超级返回与子类是否“兼容”,都是为ivars提供空间并进一步子类化或者是一个可怕的bug(当然,除非有问题logging)。 所以,一般来说,你不必担心检查课堂。 但是,请阅读文档。 请参阅NSString文档中有关子类NSString的部分。

我知道我的答案有点迟,但是我无法阻止自己发布一个链接,我发现这个链接对于清除我对这个问题的怀疑非常有用。

Matt Gallagher:当你指定[super init]给自己时,这意味着什么?

编辑:根据评论,这里是链接中的要点

理解为什么self=[super init]; 我们需要考虑很多方面。 我们一个一个去解决。

什么是self

每个方法都有两个隐藏的参数: self_cmd 。 所以方法调用

 - (id)initWithString:(NSString *)aString 

被编译器改变成这样的函数调用

 id initWithString(id self, SEL _cmd, NSString *aString); 

为什么我们需要自我?

现实情况是,编译器使用self参数来parsing对方法内的实例variables的引用。

假设我们有一个setValueToZero方法, value是它所属类的实例variables,那么实现

 - (void)setValueToZero { value = 0; } 

会被编译器转换成这样的函数

 void setValueToZero(id self, SEL _cmd) { self->value = 0; } 

init被调用时, self已经有了一个值吗?

以下是一个典型的对象创build和初始化的例子。

 [[MyClass alloc] initWithString:@"someString"] 

在这里,当我们进入initWithString方法的时候,self会将新分配的对象作为它的值(也就是来自[MyClass alloc]的返回值)。 事实上,它几乎保证是正确的,最终的价值。

为什么self = [super init];

这是因为[super init]被允许做三件事之一:

  1. 返回自己的接收器( self指针不变),并初始化了inheritance的实例值。
  2. 用初始化的inheritance实例值返回一个不同的对象。
  3. 返回nil ,表示失败。

在第一种情况下,作业对self没有影响。 在第三种情况下,初始化失败, self被设置nil ,并返回。

第二种情况是指派给self的原因。 考虑以下几点

 - (id)initWithString:(NSString *)aString { self = [super init]; if (self) { instanceString = [aString retain]; } return self; } 

我们希望从中转换

 instanceString = [aString retain]; 

 self->instanceString = [aString retain]; 

以正确的价值行事,因此我们必须改变self的价值。

何时会[super init]返回一个不同的对象?

在以下情况之一

  1. Singleton对象(总是返回单例,而不是任何后续的分配)
  2. 其他唯一的对象( [NSNumber numberWithInteger:0]总是返回全局的“零”对象)
  3. 当您初始化超类的实例时,类簇会替代私有子类。
  4. select根据传递给初始值设定项的参数重新分配相同(或兼容)类的类。

除最后一种情况外,如果它们发生变化,则继续初始化返回的对象是一个错误 – 返回的对象已经完全初始化,并且不再需要与您的类相关联。 所以更好的init方法如下

 - (id)initWithString:(NSString *)aString { id result = [super init]; if (self == result) { instanceString = [aString retain]; } return result; } 

结论

您不需要将[super init]指派给self以使大多数类都可以工作。 在一些模糊的情况下,这实际上是错误的事情。

那为什么我们继续分配self呢? 这是一个初始化器的传统模板,虽然在某些情况下是错误的,但在其他情况下,写这个方法是正确的。

基本上每个Objective-C类都是一个子类。 它是你指定的一个类或NSObject。

在子类(你正在处理的类)中,你可以调用self = [super init]

这基本上做的是调用超类(我上面提到的)init方法(构造函数),并将其分配给当前类。

这确保了超类的初始化方法被调用。

现在如果(自我)这基本上检查,如果上面的一段代码工作。

这样做是为了确保如果你调用超类的实例variables,你就可以这样做。

在大多数情况下,将自己设置为[super init]将不会执行任何操作,因为[super init]会自动返回自身。 但是有一些罕见的情况,super init会返回不同的东西。 如果由于某种原因未能初始化超类,它可能返回nil,或者可能决定返回一个完全不同的对象。

资源


实现指定的初始化程序

**

**在一个方法中,self是一个隐式的局部variables。 不需要声明它,它自动设置为指向发送消息的对象。 (在Android编程中就是这样的。)通常情况下,使用self来让对象可以发送消息给自己。 示例:

  return self; 

**

**当我们重写一个方法时,我们想要保持超类的方法正在做,并让你的子类添加新的东西。 为了方便起见,在Objective-C中有一个叫做super的编译器指令。 超级怎么样? 通常,当您向对象发送消息时,search该名称的方法将从对象的类中开始。 如果没有这样的方法,search继续在对象的超类中。 search将继续inheritance层次结构,直到find合适的方法。 (如果它到达层次结构的顶部并且没有find方法,则抛出exception)。 当我们向super发送消息的时候,我们正在向自己发送消息,但是search方法会跳过对象的类并从超类开始。 在上面的例子中,我们发送init消息给super。 这将调用NSObject的init方法。

因为你必须以某种方式初始化对象,并且大概你想做任何初始化,所以需要完成一个超类,因为你是从这个超类中下来的。