代码之家  ›  专栏  ›  技术社区  ›  Pablo

为什么要调用self=[super init]

  •  32
  • Pablo  · 技术社区  · 15 年前

    init 方法。为什么要调用并返回超类的值 初始化

    我会很感激的例子,为什么我需要它的可可超类和非可可。

    6 回复  |  直到 15 年前
        1
  •  46
  •   Imanou Petit    11 年前

    你是说为什么

    self = [super init];
    

    [super init];
    

    两个原因:

    1. 超类可能会选择用另一个对象替换+alloc返回的self。这种情况很少见,但最常发生在 class clusters

    针对迈克尔的评论编辑:

    我可以理解为什么我需要保存并返回[super init]。但这仅仅是惯例和美貌让我们把self作为一个临时变量来传递结果吗?

    -(id) init
    {
        self = [super init];
        if (self != nil)
        {
            myBoolIvar = YES; 
           // The above is an implicit version of self->myBoolIvar = YES;
        }
        return self;
    }
    

    赛尔夫显然必须指向正确的记忆块,即你要返回的那块。

    另一点是,如果super init返回不同的类实例,那么该行之后的其余代码甚至可能没有意义,导致内存泄漏和崩溃,甚至不讨论从该类实例化的对象。

    那可能是个问题。如果我将NSNumber子类化,[super init]决定返回一个NSString(它可以-没有什么可以阻止它),那显然是一场灾难。无论从-init返回什么,都必须与子类“兼容”,即为ivar提供空间并进一步子化,否则这是一个可怕的bug(当然,除非问题被记录在案)。所以,一般来说,你不需要担心检查类。但是,一定要阅读文档。例如,请参阅NSString文档中有关NSString子类化的部分。

        2
  •  26
  •   Jomoos    12 年前

    Matt Gallagher: What does it mean when you assign [super init] to self?

    编辑: 根据评论,以下是链接中的要点

    去理解为什么 self=[super init];

    是什么 self

    每个方法都有两个隐藏参数: 自己 _cmd . 所以方法调用

    - (id)initWithString:(NSString *)aString
    

    由编译器更改为如下函数调用

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

    实际情况是编译器使用 参数来解析对方法内实例变量的任何引用。

    假设我们有一个方法 setValueToZero value

    - (void)setValueToZero
    {
        value = 0;
    }
    

    将由编译器转换成如下函数

    void setValueToZero(id self, SEL _cmd)
    {
        self->value = 0;
    }
    

    已经有一个值当 init 叫什么名字?

    下面是一个典型的对象创建和初始化示例。

    [[MyClass alloc] initWithString:@"someString"]
    

    initWithString 方法,self将新分配的对象作为其值(即 [MyClass alloc] ). 事实上,几乎可以保证它是正确的最终值。

    self = [super init]; ?

    [super init]

    1. 返回自己的接收器 自己 指针未更改)的继承实例值初始化。
    2. 返回初始化了继承实例值的其他对象。
    3. nil ,表示失败。

    自己 . 在第三种情况下,初始化失败, 自己 设置为 它被归还了。

    把任务分配给 是第二个案子。考虑以下几点

    - (id)initWithString:(NSString *)aString
    {
        self = [super init];
        if (self)
        {
            instanceString = [aString retain];
        }
        return self;
    }
    

    我们想要从

    instanceString = [aString retain];
    

    self->instanceString = [aString retain];
    

    自己 .

    [超级初始化] 返回其他对象?

    在下列情况之一

    1. Singleton对象(总是返回Singleton,而不是任何后续的分配)
    2. 其他独特的物体( [NSNumber numberWithInteger:0] 始终返回全局“零”对象)
    3. 基于传递给初始值设定项的参数选择重新分配相同(或兼容)类的类。

    在最后一种情况下,如果返回的对象发生更改,则继续初始化它是一个错误,返回的对象已经完全初始化,不再需要与类相关。因此,更好的初始化方法如下

    - (id)initWithString:(NSString *)aString
    {
        id result = [super init];
        if (self == result)
        {
            instanceString = [aString retain];
        }
        return result;
    }
    

    你不需要指定 [超级初始化] 自己 使大多数课程都有效。在一些晦涩难懂的情况下,这样做实际上是错误的。

    为什么我们要继续分配给 ? 它是初始值设定项的传统模板,虽然在某些情况下它是错误的,但在其他情况下它是正确的,因为已经编写了预期这种方法。

        3
  •  4
  •   Venu Gopal Tewari    10 年前

    基本上每个Objective-C类都是一个子类。它要么是您指定的某个类,要么是NSObject。

    在您调用的子类(您正在处理的类)中

    现在为 如果(自身) 这基本上检查上述代码是否有效。

        4
  •  1
  •   Ferruccio    15 年前

    在大多数情况下,将self设置为[super init]没有任何作用,因为[super init]无论如何都会返回self。不过,在一些罕见的情况下,[super init]会返回一些不同的结果。如果由于某种原因未能初始化超类,它可能返回nil,或者它可能决定返回一个完全不同的对象。

        5
  •  1
  •   Nam N. HUYNH    9 年前


    Implementing The Designated Initializer

    **

    自己

    ** 在方法中,self是一个隐式局部变量。不需要声明它,它会自动设置为指向发送消息的对象(在Android编程中是这样的。)通常,self用于对象向自身发送消息。示例如下:

     return self;  
    

    超级的

    当我们重写一个方法时,我们希望保持超类的方法在做什么,并让您的子类在上面添加新的内容。为了更简单,Objective-C中有一个名为super的编译器指令。 通常,当您向对象发送消息时,该名称的方法的搜索从对象的类开始。如果没有这样的方法,则在对象的超类中继续搜索。在找到合适的方法之前,将继续向上搜索继承层次结构(如果它到达层次结构的顶部,但找不到任何方法,则会引发异常)。

        6
  •  0
  •   jer    15 年前

    因为您必须以某种方式初始化对象,并且假定您要执行任何需要执行的超类初始化,因为您是从它开始下降的。