Objective-c:关于self = [super init]的问题

时间:2013-09-09 07:04:03

标签: ios objective-c


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

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

希望有人能为我澄清这一点。谢谢。

8 个答案:

答案 0 :(得分:44)

假设MyClassBaseClass的子类,则会发生以下情况 你打电话

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

    • 执行MyClass的基本初始化并返回self
    • 放弃self并分配/初始化并返回其他对象。
  6. 回到self的{​​{1}}方法:init现在要么

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

  8. 所以,如果我正确理解你的问题,那么重点是

    MyClass

    使用self参数调用[super init] 的超类实现, 这是一个init对象,而不是self对象。

答案 1 :(得分:6)

如果您在if条件中提出问题self = [super init],则表明具体含义。

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

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

最后,如果条件为if(self = [super init]),则将其放入,这意味着您正在检查类的对象是否存在,以防止应用程序的犯规行为。

我认为现在很清楚!!!

答案 2 :(得分:3)

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

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

  

“超级工作怎么样?通常当您向对象发送消息时,   搜索该名称的方法从对象的类开始。如果   没有这样的方法,搜索继续在超类中   宾语。搜索将继续继承继承层次结构,直到a   找到合适的方法。 (如果它到达层次结构的顶部并且   没有找到方法,抛出异常。)“

     

“当您向超级发送消息时,您正在向自我发送消息,   但是搜索方法跳过对象的类并从中开始   超类。“

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

objc_msgSendSuper(self, @selector(init));

答案 3 :(得分:2)

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

以下方法:

logpath

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

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

请参阅此链接了解更多信息:

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

答案 4 :(得分:2)

Self = [super init];

根据JAVA,这个表示指向实例本身的指针,因此对象可以自己发送消息。

目标C中自我的相同内容,

根据JAVA,超级意味着允许访问基类或父类

目标C中的超级相同,

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

答案 5 :(得分:1)

来自Apple's Documentation

因为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... 
}

答案 6 :(得分:1)

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

答案 7 :(得分:1)

[super init]与[ self superclass_variant_of_init]相同

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

[[self superclass] init];