[Obj-C笔记] "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方法都能保证安全了。

转载于:https://www.cnblogs.com/yaokoo/archive/2012/12/11/2813322.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
typedef struct { int *base; int front; int rear; int num,size; } MyCircularQueue; MyCircularQueue* myCircularQueueCreate(int k) { MyCircularQueue *obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); if(!obj) return NULL; obj->base=(int*)malloc(k*sizeof(int)); obj->front=obj->rear=0; obj->num=0; obj->size=k; return obj; } bool myCircularQueueIsEmpty(MyCircularQueue* obj); bool myCircularQueueIsFull(MyCircularQueue* obj); bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) { if(myCircularQueueIsFull(obj)) return false; obj->rear=(obj->rear+1)%obj->size; obj->base[obj->rear]=value; obj->num++; if(obj->num==1) obj->front=obj->rear; return true; } bool myCircularQueueDeQueue(MyCircularQueue* obj) { if(myCircularQueueIsEmpty(obj)) return false; obj->base[obj->front]=-1; obj->front=(obj->front+1)%obj->size; obj->num--; return true; } int myCircularQueueFront(MyCircularQueue* obj) { if(myCircularQueueIsEmpty(obj)) return -1; else return obj->base[obj->front]; } int myCircularQueueRear(MyCircularQueue* obj) { if(myCircularQueueIsEmpty(obj)) return -1; else return obj->base[obj->rear]; } bool myCircularQueueIsEmpty(MyCircularQueue* obj) { return(obj->num==0); } bool myCircularQueueIsFull(MyCircularQueue* obj) { return(obj->num==obj->size); } void myCircularQueueFree(MyCircularQueue* obj) { free(obj->base); obj->base=NULL; free(obj); obj=NULL; } /** * Your MyCircularQueue struct will be instantiated and called as such: * MyCircularQueue* obj = myCircularQueueCreate(k); * bool param_1 = myCircularQueueEnQueue(obj, value); * bool param_2 = myCircularQueueDeQueue(obj); * int param_3 = myCircularQueueFront(obj); * int param_4 = myCircularQueueRear(obj); * bool param_5 = myCircularQueueIsEmpty(obj); * bool param_6 = myCircularQueueIsFull(obj); * myCircularQueueFree(obj); */
最新发布
07-13

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值