24


self = [super init]我在init方法 中见过。我不明白为什么。不会[super init]返回超类吗?如果我们指出self = [super init],我们没有得到self = superclass吗?
这是一个示例代码片段

- (id)init 
{
    if (self = [super init]) {
        creationDate = [[NSDate alloc] init];
    }
    return self;
}

希望有人可以为我澄清这一点。谢谢你。

4

8 回答 8

45

假设它MyClass是 的子类BaseClass,当您调用时会发生以下情况

MyClass *mc = [[MyClass alloc] init];
  1. [MyClass alloc]分配一个MyClass.
  2. init消息被发送到该实例以完成初始化过程。
    在那个方法中,self(它是所有 Objective-C 方法的隐藏参数)是步骤 1 中分配的实例。
  3. [super init]调用具有相同(隐藏) 参数的超类实现。(这可能是你理解错误的一点。)initself
  4. 在 的init方法中BaseClassself仍然是 的同一个实例MyClass这个超类的 init 方法现在可以

    • 执行self和 return的基本初始化self,或者
    • 丢弃self并分配/初始化并返回不同的对象。
  5. 回到:的init方法现在是MyClassself = [super init]

    • 在步骤 1 中分配的MyClass对象,或
    • 有些不同。(这就是为什么人们应该检查并使用这个返回值。)
  6. 初始化完成(使用self由超类 init 返回的)。

所以,如果我正确理解了你的问题,重点是

[super init]

使用参数调用超类实现,init参数selfMyClass对象,而不是BaseClass对象。

于 2013-09-09T07:50:27.450 回答
6

正如您在 if Condition 中的 Questionself = [super init]暗示了一个特定的含义。

首先[super init]给出当前正在使用的现有类的超类的初始化。Using[super init]给出了超类初始化,表明该类的对象存在。

现在,当您使用self = [super init]这意味着您正在将类分配给自我以进一步利用同一类。

最后你把它放在 if 条件中,因为if(self = [super init])这意味着你正在检查类的对象是否存在,以防止应用程序的错误行为。

我想现在很清楚了!!!

于 2013-09-09T07:51:15.547 回答
3

@MartinR 有一个很好的答案。但是你有没有想过为什么“[super init] 用相同的(隐藏的)self 参数调用 init 的超类实现。(这可能是你理解错误的一点。)”在他的第三点有效?

这是 Big Nerd Ranch 指南第 3 版第 2 章 Objective C 的摘录,阐明了这一点

“超级是如何运作的?通常,当您向对象发送消息时,会在对象的类中开始搜索具有该名称的方法。如果没有这样的方法,则在对象的超类中继续搜索。搜索将继续沿继承层次结构向上,直到找到合适的方法。(如果它到达层次结构的顶部并且没有找到方法,则抛出异常。)”</p>

“当你向 super 发送消息时,你是在向self发送消息,但是对方法的搜索会跳过对象的类并从超类开始。”</p>

此代码显示 iOS 运行时如何执行此任务

objc_msgSendSuper(self, @selector(init));
于 2014-03-31T04:23:28.883 回答
2

您声明的每个方法都有两个隐藏参数:self 和 _cmd。

以下方法:

- (id)initWithString:(NSString *)aString;

由编译器转换为以下函数调用:

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

有关更多信息,请参阅此链接:

http://www.cocoawithlove.com/2009/04/what-does-it-mean-when-you-assign-super.html

于 2015-06-14T16:57:15.960 回答
2

自我 = [超级初始化];

根据 JAVA,意味着指向实例本身的指针,因此对象可以向自己发送消息。

在目标 C 中,Self的含义相同,

根据 JAVA,Super表示允许访问基类或父类

在目标 C中Super的含义相同,

现在init实例来完成初始化过程。

于 2017-01-19T07:30:03.030 回答
1

来自Apple 的文档

因为 init... 方法可能返回 nil 或一个对象,而不是显式分配的对象,所以使用 alloc 或 allocWithZone: 返回的实例而不是初始化程序返回的实例是危险的。考虑以下代码:

id myObject = [MyClass alloc];
[myObject init];
[myObject doSomething];

上面示例中的 init 方法可能返回 nil 或替换为不同的对象。因为您可以在不引发异常的情况下向 nil 发送消息,所以在前一种情况下不会发生任何事情,除非(可能)令人头疼的调试问题。但是您应该始终依赖于初始化的实例,而不是刚刚分配的“原始”实例。因此,您应该将分配消息嵌套在初始化消息中,并在继续之前测试从初始化程序返回的对象。

id myObject = [[MyClass alloc] init];
if ( myObject ) {
    [myObject doSomething];
} else {
    // error recovery... 
}
于 2013-09-09T07:08:35.550 回答
1

我会认为它是初始化所有超级变量等,然后在返回之前初始化扩展类变量。

于 2013-09-09T07:32:18.553 回答
1

[super init]与 [ self superclass_variant_of_init]相同

如果要向超类发送消息,还有另一种方法(不使用运行时库):

[[self superclass] init];
于 2013-09-09T09:24:54.577 回答