zoukankan      html  css  js  c++  java
  • self = [super init]

     
    父类进行初始化时,用的是子类对象指针self,父类的init方法有可能对这个指针指向的内存区作了大的变更(有可能把这个指针所指的内存释放了,重新分配了另一块内存区域返回来,这时这个返回的指针与原来的指针是指向不同地址的),所以父类初始化后要重新返回指针。父类返回的和子类的self的类型都为id类型(通用类型)。父类的init方法若返回的指针与self不一样,在父类的init方法中已作了release和新的内存分配,不需要自己再去release sef,直接用父类init方法返回的指针就可以了。
     
    下面是转自: view plaincopyprint?
    [plain]
    1. - (id)init {
    2. self = [super init]; // Call a designated initializer here.
    3. if (self != nil) {
    4. // 省略其他细节
    5. }
    6. return self;
    7. }

    容易让人困惑的地方在于,将父类初始化之后,将其返回的对象指针覆盖当前对象的指针。

    这种方式令人费解,目前暂时找不到官方解释这么做的原因。

    官方文档 有解释。

    我们先分以下几种情况分别分析:(假设superSelf是[super init]的返回值)

    1 superSelf == nil

    此时父类初始化失败,self随之被赋值为nil并返回,表现正常。

    2 superSelf == self

    大部分类的初始化都是这个结果。此时赋值没有任何影响。

    3 superSelf != self

    这种情况正是大部分人疑惑的地方。执行self = [super init]之后,

    我们创建的对象将会被重定向到另外一块内存上。接下来重点解释这种情况。

    首先,出现父类指针跟子类指针不一样的情况其实就是父类的init方法返回的对象跟原先创建的对象不一样,分为以下几种:

    1 单件。

    此时如果执行self = [super init]将使所有子类指向这个单件的内存。

    这不仅使所有子类互相修改数据,甚至访问子类自己增加的变量的时候,可能会崩溃。

    建议不要继承单件、或者保证单件的子类也是单件。

    2 ClassClusters(类簇),初始化方法返回了不同的子类。

    以下是对象初始化后,返回不同的子类的例子:

    1. NSString *str1 = [NSString alloc];
    2. NSString *str2 = [str1 initWithString:@"hello"];

    上面的str1和str2是不一样的对象,存在于不同的内存块中,在GNUStep里面,str1是GSPlaceholderString对象,str2是GSCInlineString对象。

    3 共享。

    先看例子:

    1. NSNumber *n1 = [[NSNumber alloc] initWithInt:1];
    2. NSNumber *n2 = [[NSNumber alloc] initWithInt:1];

    以上的n1和n2,指向了同一块内存!

    由于NSNumber是创建之后就不能修改的对象,所以Foundation在这里做了一些优化,相同数值的NSNumber对象将共享同一块内存。

    4 父类可能在初始化中释放了当前的对象并创建了新的内存区域。

    这时,子类需要将self指向新的内存区域才能正常工作。所以一定要执行self = [super init];

    总结:

    在初始化方法中使用self = [super init]语句是Objective-C的标准做法。

    一般情况下都要用以上语句来防止父类改变对象的内存地址导致self指针指向无效内存。

    在父类是单件、类簇或者有共享资源的时候,必须依照实际情况考虑是否加上这行代码。

    总之,当需要继承父类的时候,调用父类的init之前,必须知道父类的init方法的工作方式。

  • 相关阅读:
    EF的连表查询Lambda表达式和linq语句
    C#.NET里面抽象类,接口,虚方法
    ASP.Net WebAPI的返回值
    IHttpActionResult不识别解决办法
    web api 开发之 filter
    SQL语句大全教程
    ASP.NET Web API 跨域访问(CORS)要注意的地方
    铁乐学python_shelve模块详解
    铁乐学python_day25_序列化模块
    铁乐学python_day24_面向对象进阶1_内置方法
  • 原文地址:https://www.cnblogs.com/qingjoin/p/2614735.html
Copyright © 2011-2022 走看看