1

当我有如下代码时:

self = [super init]

self 指向 super 吗?如果是这样,你为什么要这个?如果我的实例对象有变量“someVal”,我将无法通过执行 [self someVal] 来获得它。正确的?

那么当 self 指向 super 时,我将如何使用 self 来访问实例变量?

4

4 回答 4

5

self 指向 super 吗?

这真的是相反的。super实际上与 相同self,只是它告诉编译器从超​​类而不是类本身开始寻找方法实现。您可以通过记录 的值superself;的值来检查这一点。你会发现它们都指向同一个地址。

当你创建一个对象时,你这样做:

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];

但是,如果您这样写,则假设您的类的初始化程序和它继承的所有类将始终返回相同的对象,并且永远不会返回nil。通过这样做,你打破了约定,严重地束缚了你自己和编写 Foo 继承的类的人——如果他们在类的未来版本中返回不同的对象,他们将破坏你的代码。此外,看起来你不知道自己在做什么。

于 2013-02-18T18:25:13.107 回答
3

self 指向 super 吗?

这个问题在实例方法中没有意义,因为实际上super并没有具体/实际的指向实例的指针,它只是表明必须调用超类的实现。并且由于在大多数对象(类簇除外)所有方法的情况下return self;,答案是否定的:指向实例的实际指针本身不会神奇地改变。

记录一下:异常是由类簇(大多数 Cocoa 容器类,例如 、 等)表现出来NSStringNSArray。这些类通常有一个初始化方法,该方法返回与最初分配的实例不同的实例,并且该类是原始类的具体子类self。例如,NSString初始化程序的实现可能是:

@implementation NSString

- (NSString *)init
{
    [self release];
    self = [[__NSCFString alloc] init];
    return self;
}

@end

这样做的原因是可以通过这种方式实现针对不同类型初始化的优化。

于 2013-02-18T18:07:09.640 回答
1

自我总是指向一个实例。当您使用 super 时,您引用的是父方法而不是父实例。

于 2013-02-18T18:07:10.900 回答
1

self表示当前类的实例。

self = [super init]表示 self 正在获取[super init].

于 2013-02-18T18:07:59.720 回答