文章目录
  1. 1. 文档更新说明
  2. 2. 前言
  3. 3. 什么是初始化器
  4. 4. 类继承的初始化规则
    1. 4.1. 两段式初始化(Two-Phase Initialization)
    2. 4.2. 两段式初始化的属性初始化规则
    3. 4.3. 类的初始化器委托的规则
  5. 5. 初始化器的继承和重写
  6. 6. 奇怪的init?和init!
  7. 7. 阅读推荐

文档更新说明

  • 最后更新 2018年03月23日
  • 首次更新 2018年03月23日

前言

  本文是基于Swift4编写,低于Swift4的版本未作测试.
  这段时间开始接触Swift4,在遇到类初始化的时候明显感受到了Swift在类,结构体等初始化过程中的严谨程度,有感而发,挑选了一部分和OC有比较大区别的语法来讲解一下.下面只讲解类,因为类比较复杂.至于结构体和枚举明显要简单很多,因为这两个没有继承功能.

什么是初始化器

  初始化器的概念应该类似构造函数,用来初始化对象属性.在Swift中,一共有两种初始化器,分别是指定初始化器便捷初始化器.这两种类型的初始化器可就大有区别了,为了确保类链(类继承)各个类的正确初始化,Swift团队为其设计了一套非常严谨的语法.

类继承的初始化规则

下面说的属性,指的就是对象属性

两段式初始化(Two-Phase Initialization)

  我估计很多人看到这个就懵了,从来没听说过,就算你看文档估计都晕乎很久.那我就粗鲁地说一下这是什么,举个例子:

假设现在有三个类ABC,继承关系如下
A -- 基类
B -- 子类
C -- 子类
A是基类,B和C都是子类.

  
  第一段: “从底部到顶部”, 这个过程就是要求先初始化子类中新增的属性,一步一步走向基类.注意,这个过程是不允许访问self关键字的.当然初始化子类的属性还是可以使用self.子类属性 = XXX,但是print(self)**或者调用方法是不被允许的.
  第二段: “从顶部到底部”, 这个过程所有类自己特有的属性已经初始化完毕了,接下来就可以修改属性了(包括父类继承来的),**self
关键字也可以直接访问了.

两段式初始化的属性初始化规则

  根据两段式初始化的原则,Swift在实际使用中有着下面的编译限制

类的初始化器委托的规则

  1. 指定初始化器必须总是向上委托(向父类)
  2. 便捷初始化器必须总是横向委托(调用本类的指定初始化器)

初始化器的继承和重写

  Swift和OC不一样,Swift默认是不会继承父类的初始化器(只有特定情况才会). Swift的这种机制防止父类的简单初始化器被一个更专用的子类继承并被用来创建一个没有完全或错误初始化的新实例的情况发生。
  要继承父类的初始化器,需要满足两个条件

1. 如果你的子类没有定义任何指定初始化器,它会自动继承父类所有的指定初始化器。
2. 如果你的子类提供了所有父类指定初始化器的实现——通过在定义中提供自定义实现的——那么它自动继承所有的父类便捷初始化器。就算你的子类添加了更多的便捷初始化器,这些规则仍然适用。

  下图是针对上面第2点,子类继承了父类的便捷初始化器之后的调用效果

奇怪的init?和init!

  简单概括一下就是:

  1. init?定义的初始化器,表示这个初始化可能会失败,失败的时候,return nil
  2. init!,一样是可失败初始化器,只不过这个失败要求触发断言

  除此之外,它也可以是指定构造器或者便捷构造器,也有继承重写等.

阅读推荐

Swift初始化
Apple Swift4.1文档

文章目录
  1. 1. 文档更新说明
  2. 2. 前言
  3. 3. 什么是初始化器
  4. 4. 类继承的初始化规则
    1. 4.1. 两段式初始化(Two-Phase Initialization)
    2. 4.2. 两段式初始化的属性初始化规则
    3. 4.3. 类的初始化器委托的规则
  5. 5. 初始化器的继承和重写
  6. 6. 奇怪的init?和init!
  7. 7. 阅读推荐