当我有以下代码时:
self = [super init]
自我指向超级?如果是这样,你为什么要这样?如果我的实例对象具有变量“someVal”,我将无法通过[self someVal]来实现它。正确的吗?
当self指向super时,我如何使用self来获取实例变量?
答案 0 :(得分:5)
自我指向超级?
实际上反过来了。 super
与self
实际上是相同的,除了它告诉编译器开始寻找以超类而不是类本身开始的方法实现。您可以通过记录super
的值和self
的值来检查这一点;你会发现他们都指向同一个地址。
创建对象时,执行以下操作:
Foo *f = [[Foo alloc] init];
alloc
分配将成为您正在创建的对象的内存,但在该内存初始化之前,它只是一块内存 - 而不是有效对象。如果Foo
是Bar
的子类而Bar
是NSObject
的子类,那么按照惯例,Foo的初始化程序将调用Bar,而Bar将调用NSObject,以便初始化按顺序继续:首先由NSObjects'-init
初始化内存,Bar的init接收返回的值并将其分配给self
。然后它继续执行任何特定于Bar的初始化,并返回self
。 Foo的-init
然后再次将返回的值赋给self
,最后进行任何特定于Foo的初始化。
分配给self
的所有内容可能看起来既冗余又令人困惑。它实际上只是一个约定,但目的是允许超类的初始值设定项返回除已分配的对象之外的一些对象,包括nil
。因此,例如,如果Bar
的初始化因某种原因失败,-[Bar init]
可能会返回nil。从nil
返回[super init]
的可能性是我们将self = [super init]
赋值置于条件内的原因:如果赋值为nil
,则跳过初始化部分,返回nil
。 -[Bar init]
也可能返回指向除已分配对象之外的对象的指针,例如当与正在创建的对象类似的对象已经存在且可以重用时。
大多数情况下,您从-init
返回的指针与从+alloc
获得的指针相同,因此您可以写这个:
Foo *f = [Foo alloc];
[f init];
但是,如果您这样写,那么您假设您的类的初始值设定项和它继承的所有类将总是返回相同的对象,并且永远不会返回{{ 1}}。通过这样做,你破坏了约定并严重妨碍了自己以及编写Foo继承的类的人 - 如果他们在类的未来版本中返回不同的对象,他们将破坏你的代码。而且,看起来你不知道自己在做什么。
答案 1 :(得分:3)
自我指向超级?
这个问题在实例方法中没有意义,因为super
实际上并不是具体/实际的实例指针,它只是表明必须调用超类的实现。因为在大多数对象(类集群除外)所有方法return self;
的情况下,答案是否:实例指向实例的指针本身并没有神奇地改变强>
对于记录:异常由类簇表示(大多数Cocoa容器类,例如,NSString
,NSArray
等。这些类通常具有初始化方法,该方法返回与最初分配的实例不同的实例,并且该类是原始self
的类的具体子类。例如,NSString
初始化程序的实现可能是:
@implementation NSString
- (NSString *)init
{
[self release];
self = [[__NSCFString alloc] init];
return self;
}
@end
这样做的原因是可以通过这种方式实现对不同类型初始化的优化。
答案 2 :(得分:1)
Self始终指向一个实例。当您使用super时,您将引用父方法而不是父实例。
答案 3 :(得分:1)
self
表示当前的类'实例。
self = [super init]
表示self获取[super init]
返回的值。