在swift中,类的继承和构造过程是需要注意的,主要是其构造过程需要进行严格的安全检查,必须符合其检查的代码方能编译,具体内容如下:


swift的构造过程是两段式的,什么是两段式呢,就是类实例的初始化,即构造器的调用和执行过程,分为两个阶段。


先来看两个阶段是怎么个分法,弄清楚两个阶段分别做了什么,就自然明白为什么要分两个阶段以及这么做的好处了。


首先来看两个图,图片来自《The Swift Programming Language》:

Swift 参数可传可不传 swift传输过程_swift


这是swift的继承链,Convenience表示遍历构造器,Designated表示指定构造器,右图可以看出:


1.便利构造器必须调用同类的指定构造器已完成属性的初始化。


2.指定构造器必须调用父类的指定构造器以完成父类属性的初始化。


这个构造链只是表示了继承关系,并没有详细给出构造过程,以下两张图片详细表示了构造过程的两个阶段:


第一阶段: 


Swift 参数可传可不传 swift传输过程_ios_02


第二阶段:

Swift 参数可传可不传 swift传输过程_继承_03


从图中可以看到,第一阶段是自下而上的,而第二阶段是自上而下的,怎么理解呢?


我们知道,在子类进行实例化的过程中,必不可少的一个步骤是:调用父类的构造方法已完成父类属性的初始化。而一个对象的存储属性就可以由此分为两类,一类是自身引入的,一类是继承自父类的。


一个对象的内存只有在其所有的存储属性全部确定之后才能完全初始化。


也就是说,我们在指定构造器中对类的存储属性初始化,必须完成自身引入的存储属性和继承自父类的存储属性这两类属性的初始化后,实例才完全初始化,如果在构造器中只初始化自身引入的存储属性,或者只初始化继承自父类的存储属性,该实例都无法完成初始化。


所以,我们初始化一个实例通常不仅要为自身引入的属性赋初值,还要调用父类的构造方法来处理父类的属性,这样每个类都对自身引入的属性初始化后,调用父类的构造方法,一层一层调用上去,最终到达了继承链顶端,实例才真正完成初始化。


在swift中,上述过程严格执行安全检查,以确保构造过程顺利完成,其第一阶段的任务就是,完成实例的完全初始化,而第二阶段的任务则是,可以由我们对已经完全初始化好的实例进行进一步的定制。


简单来说就是:


第一阶段自下而上,为所有属性赋初值,最终到达继承链顶端,所有属性都初始化完成,实例完全初始化。


第二阶段自上而下,从继承链顶端开始向下,给了我们在每一层对实例进行再定制的权利,我们可以在这个过程中在任意一层对实例进行修改。


反映在代码上: 


Swift 参数可传可不传 swift传输过程_Swift 参数可传可不传_04




可以看到,对子类的初始化严格按照swift的要求去做,先初始化自身引入的属性,再调用父类的构造器初始化父类的属性,最后对实例进行随意定制。




需要明确的是,这么做并不是因为这样的流程更加清晰,而是swift严格要求必须按照这样的顺序,下面就是swift为了保证两段式构造过程顺利完成而进行的四个安全检查: 


Swift 参数可传可不传 swift传输过程_代码_05





从第四条可以看出,只有在第一阶段完成之后,实例才真正初始化完成。



两个阶段的详细过程解读如下: 



Swift 参数可传可不传 swift传输过程_ios_06



Swift 参数可传可不传 swift传输过程_Swift 参数可传可不传_07