• [ObjC笔记] "self = [super init]"的解释与潜藏bug


    [Obj-C笔记] "self = [super init]"的解释与潜藏bug

    Objective-C的推荐init方法写法如下:

    - (id) init
    {
        if(self = [super init])
        {
            //为子类增加属性进行初始化
        }
        return self;
    }

    这里涉及了几个问题,

    1. [super init]的作用:

    面向对象的体现,先利用父类的init方法为子类实例的父类部分属性初始化。

    2. self 为什么要赋值为[super init]:

    简单来说是为了防止父类的初始化方法release掉了self指向的空间并重新alloc了一块空间。这时的话,[super init]可能alloc失败,这时就不再执行if中的语句。

    3. super作为消息接受者的实质:

    super并不是真正的指针,[super message]的实质是由self来接受父类的message。需要注意的是,[super message]中,message方法出现的self为[super message]语境中的self,即子类实例。

    潜藏的bug:

    假设有父类AObj与子类BObj。

    当AObj的init方法如下:

    - (id) init
    {
        id tmp = self;
        self = [AObj alloc];
        [tmp release];
        //other staffs
        return self;
    }

    BObj的init方法如下:

    - (id) init
    {
        if(self = [super init])
        {
            //other staffs
        }
        return self;
    }

    这时编译能通过,但当BObj的实例使用到BObj扩充的属性时,就会出现一个运行时错误。错误的原因在于AObj的init方法用[AObj alloc]重新获得了一块仅仅适合存放AObj实例的空间。而BObj的init方法以为这是块适合存放BObj的空间。当试图读写BObj的扩充属性时便会产生运行时错误。

    因此,当init方法需要重新alloc一块空间时,正确的写法如下:

    - (id) init
    {
        id tmp = self;
                        
        self = [[self class] alloc];
                        
        [tmp release];
        //other staffs
        return self;
    }

    注意[self class]将获得self指向的实例对应的类实例,本例中便是BObj。这样AObj的任何子类的init方法都能保证安全了。

    如果有什么事情让你感到恐惧或者兴奋,那就去做吧!
  • 相关阅读:
    uvalive 3644 X-Plosives
    uva 11997 K Smallest Sums
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) D. Sorting the Coins
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) C. Classroom Watch
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) B. Divisiblity of Differences
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) A. Trip For Meal
    1004. 成绩排名 (20)
    1003. 我要通过!(20)
    1002. 写出这个数 (20)
    1001. 害死人不偿命的(3n+1)猜想 (15)
  • 原文地址:https://www.cnblogs.com/yaokoo/p/2813322.html
Copyright © 2020-2023  润新知