先来看两个阶段是怎么个分法,弄清楚两个阶段分别做了什么,就自然明白为什么要分两个阶段以及这么做的好处了。
首先来看两个图,图片来自《TheSwiftProgrammingLanguage》:
这是swift的继承链,Convenience表示遍历构造器,Designated表示指定构造器,右图可以看出:
这个构造链只是表示了继承关系,并没有详细给出构造过程,以下两张图片详细表示了构造过程的两个阶段:
第一阶段:
第二阶段:
从图中可以看到,第一阶段是自下而上的,而第二阶段是自上而下的,怎么理解呢?
也就是说,我们在指定构造器中对类的存储属性初始化,必须完成自身引入的存储属性和继承自父类的存储属性这两类属性的初始化后,实例才完全初始化,如果在构造器中只初始化自身引入的存储属性,或者只初始化继承自父类的存储属性,该实例都无法完成初始化。
所以,我们初始化一个实例通常不仅要为自身引入的属性赋初值,还要调用父类的构造方法来处理父类的属性,这样每个类都对自身引入的属性初始化后,调用父类的构造方法,一层一层调用上去,最终到达了继承链顶端,实例才真正完成初始化。
在swift中,上述过程严格执行安全检查,以确保构造过程顺利完成,其第一阶段的任务就是,完成实例的完全初始化,而第二阶段的任务则是,可以由我们对已经完全初始化好的实例进行进一步的定制。
简单来说就是:
反映在代码上:
需要明确的是,这么做并不是因为这样的流程更加清晰,而是swift严格要求必须按照这样的顺序,下面就是swift为了保证两段式构造过程顺利完成而进行的四个安全检查:
从第四条可以看出,只有在第一阶段完成之后,实例才真正初始化完成。
两个阶段的详细过程解读如下: