【问题标题】:Assign the return object of the superclass to self将超类的返回对象赋值给self
【发布时间】:2011-02-07 14:28:14
【问题描述】:

我现在已经阅读了很多关于这个的帖子,但我仍然不明白。我会申请一个答案而不是一个链接,因为我可能已经阅读过了。

if (self = [super init]) {

}

return self;

当我调用 [super init] 时,我知道我正在调用“self”(对象地址)上的方法,但我正在超类中启动“方法搜索”。当它返回时,我将对象类型 id 分配给 self...这就是我迷路的地方。

我是否将“self”作为初始化对象分配给 self..?

我知道,如果初始化程序的超类实现返回 nil,我正在执行此检查以停止初始化,但是我不明白我在分配给 self....我认为 self 是内存中当前对象的地址.

提前致谢

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    对我来说,这个任务总是显得有些古怪。它的要点是,超类可能希望返回一些其他实例,而不是最初分配的实例:

    id foo = [[Foo alloc] init];
    
    @interface Foo : SuperFoo {…}
    @implementation Foo
    
    - (id) init
    {
        self = [super init];
        if (!self)
            …;
        return self;
    }
    
    @interface SuperFoo : NSObject {…}
    @implementation SuperFoo
    
    - (id) init
    {
        [self release];
        return [OtherClass alloc];
    }
    

    这确实很疯狂,但事实是[super init] 可能返回一个与之前的self 不同的对象。请参阅Mike Ash’s blog post,这应该会让super 变得清晰。

    【讨论】:

    • 啊,所以你将初始化器的超类实现中的返回对象分配给 self...的唯一原因是因为它可能返回除...self之外的其他对象?
    • 是的,这就是我的理解。
    • 你能告诉我一个基础类,它像你的 SuperFoo 一样在 init 方法中重新分配实例吗?
    • 不,这不是唯一的原因。另一个原因是,如果初始化失败,对[super init] 的调用可能会返回nil,在这种情况下,您的init 方法也应该返回nil
    • @phix:Ash 文章中提到了一些特殊情况,比如类集群。我自己使用了一个更简单的初始化程序,因为我发现官方的 init 习语令人震惊,我希望当我对某些可疑的东西进行子类化时,我会记住这些东西。 (这可能是一场等待发生的灾难:)
    【解决方案2】:

    有两个原因,为什么该分配很重要:

    1. 如果初始化失败,超类的指定初始化程序 (di) 可能返回 nil
      在这种情况下,如果不将其返回值分配给self,您最终将处于完全不安全的状态——很可能,您的超类的 di 将释放 self 指向的对象以不泄漏记忆。
      如果您继续使用该实例并且很幸运,您应该会在不远的将来看到崩溃。如果你没那么幸运,你会弄乱其他对象的内部状态,并在程序崩溃之前丢失或损坏用户数据。
    2. Cocoa(Touch) 中有很多类——像 NSStringNSArray 这样的类集群可能是最突出的例子——它们可能会返回与它们的 di 不同的实例。
      例如,您将从 [NSString alloc] 收到的指针几乎肯定不会与您从随后对 initWithFormat:@"Hello %@!", @"foo" 的调用中获得的相同。

    【讨论】:

      【解决方案3】:

      让我们把它分成更小的块:

      1- 当你调用 [super init] 时,你让你的超类首先运行它的 init 函数,这样它就可以初始化你继承的对象,通常是 NSObject 或你决定扩展的任何超类。 超级 init 函数将在该过程结束时返回 self ,就像您在 init 函数中所做的一样

      2- 当您执行分配时:self = [super init] 您实际上将返回值从您的超级分配到您自己的。

      3- 围绕该分配的 if 实际上评估了超级初始化调用的成功/失败,因为如果它失败了,您将获得 nil 和分配对自己来说是零。所以评估 nil 将返回 false 并且你不会运行你的初始化代码。

      4- 最终你也会返回 self(如果失败则返回 nil / 如果成功则返回实际对象)

      希望清除它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-14
        • 2017-12-01
        相关资源
        最近更新 更多