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方法的工作方式。

关于 self = [super init];的更多相关文章

  1. [转] "self = [super init]"的解释与潜藏bug

    Objective-C的推荐init方法写法如下: - (id) init { if(self = [super init]) { //为子类增加属性进行初始化 } return self; } 这里 ...

  2. OC self = [super init] , 点语法 , @property

    OC self = [super init] , 点语法 , @property 构造方法为啥这么写? self = [super init]; [super init] 的结果可能有三种: 第一种: ...

  3. iOS self = [super init]

    self = [super init] 这个问题一直不太明白,今天研究了一下,在stackoverflow找到了下面的答案: http://stackoverflow.com/questions/29 ...

  4. [super init]方法的调用

    当重新覆盖父类的init方法时,需要调用[super init]方法确认父类中的init是返回一个实例,而不是一个空的实例. 那为什么要调用这个呢? 我得猜测是这样的:因为这是一个初始化方法,需要对对 ...

  5. Swift - Property ''not initialized at super.init call

    Property ''not initialized at super.init call 这个错误应该挺常见的的,为什么在百度上没有找到呢,stack over flow找到了,也不能说是什么解决办 ...

  6. 刨根问底:对于 self = [super init] 的思考

    对象初始化有两种方式:[class new] 与 [[class alloc] init] 对于后者,有分配和初始化的过程,alloc 从应用程序的虚拟地址空间上为该对象分配足够的内存,并且将新对象的 ...

  7. 关于self和super在oc中的疑惑与分析 (self= [super init])

    这个问题貌似很初级,但很容易让人忽略,me too .直到在一次面试时被问到,稀里糊涂的回答了下.实在惭愧, 面试一定都是很注重 基础的,不管高级还是初级. 虽然基础好跟基础不好都可以写代码,网上那么 ...

  8. swift中的如果在构造方法中使用KVC, 调用了super.init(), 报错, 基本数据类型属性找不到

    swift要求, 属性必须有初始化值, 如果不对其赋值, 可以加一个?系统会默认给其包装一个可选值(直说就是nil) 如果定义一个基本类型, 建议直接赋值, 不建议使用? 下面说下标题中的问题 有时候 ...

  9. self = [super init] 最终解释

    答:      init 中调用super的 init方法来初始化自己所包含有的父类信息 1.内存分配      内存应该在[Class alloc]的时候就已经分配了,大小和类型应该由对应的Clas ...

  10. self = [super init]

    Objective-C的推荐init方法写法如下: - (id) init { if(self = [super init]) { //为子类增加属性进行初始化 } return self; } 返回 ...

随机推荐

  1. nor flash的一般操作与分析

    是现在市场上两种主要的非易失闪存技术.Intel于1988年首先开发出NOR Flash 技术,彻底改变了原先由EPROM(Electrically Programmable Read-Only-Me ...

  2. python中多重继承与获取对象

    1.python中多重继承 除了从一个父类继承外,Python允许从多个父类继承,称为多重继承. 多重继承的继承链就不是一棵树了,它像这样: class A(object): def __init__ ...

  3. html4与html5的区别

    一.HTML5更加灵活,支持下列多种形式 1.标签名可以大写(不推荐) -<SpAN>这个HTML5也的认</SpAN> 2.属性双引号可选(推荐添加双引号) -<div ...

  4. C++中int转为char 以及int 转为string和string 转int和字符串的split

    1.对于int 转为char 直接上代码: 正确做法: void toChar(int b) { char u; ]; _itoa( b, buffer, ); //正确解法一 u = buffer[ ...

  5. ELK分布式日志收集搭建和使用

    大型系统分布式日志采集系统ELK全框架 SpringBootSecurity1.传统系统日志收集的问题2.Logstash操作工作原理3.分布式日志收集ELK原理4.Elasticsearch+Log ...

  6. [POI2013]BAJ-Bytecomputer

    题目描述 A sequence of integers from the set is given. The bytecomputer is a device that allows the foll ...

  7. Graph_Master(连通分量_A_双连通分量+桥)

    hdu 5409 题目大意:给出一张简单图,求对应输入的m条边,第i-th条边被删除后,哪两个点不连通(u,v,u<v),若有多解,使得u尽量大的同时v尽量小. 解题过程:拿到题面的第一反应缩点 ...

  8. Mongo, Express, Angular, Node-- MEAN Stack搭建

    前言 作为一个从后端转全栈的码农,我一直使用express,jade & bootstrap, jquery的组合.重复了几次相同的工作后,看到网上开始流行MEAN Stack,于是也对其研究 ...

  9. struts2——上传文件

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  10. Kruskal算法-最小生成树

    2017-07-26  10:32:07 writer:pprp Kruskal算法是根据边的加权值以递增的方式,一次找出加权值最低的边来建最小生成树:并且每次添加的边不能造成生成树有回路,直到找到N ...