谈谈Swift里的初始化

96
雨墨心
2017.09.24 02:41* 字数 1127

Swift里的初始化相比于OC复杂了不少。Swift里的初始化并不返回值。而是确保在第一次使用该类型的实例之前,能够充分的正确的初始化该实例。
初始化器用关键字init表示。而对于值类型(结构体、枚举)和引用类型(类)初始化是不同的。
先说类类型。对于一个类class来说,初始化分为指定初始化器和便利初始化器两种。指定初始化器就是用init关键字声明的,而便利初始化器则在init前面用convience 。

convenience init(parameters) {
   
}

指定初始化器是主要的的初始化手段,而便利初始化器是辅助的初始化手段。因为一个类必须要有指定初始化器,而便利初始化器是可选的,为了方便的。
便利初始化器可以调用其它初始化器,但是最终必须调用指定初始化器。而指定初始化器最终必须调用父类(如果有)指定初始化器。关系像这张图。



编译器会对类类型进行四道安全检查。
1、在调用父类初始化器之前,指定初始化器必须确保该类引入的所有属性被充分初始化。
2、在对继承而来的属性赋值之前,需要先调用父类的初始化。
3、便利初始化器必须先调用该类的其它初始化器,才能对该类的属性赋值。
4、因为类类型的初始化分为两个过程,在第一阶段完成之前,无法访问self(是访问self自己而不是赋予属性),无法访问实例属性或者方法。

类类型初始化的两个阶段:
阶段1:
·指定初始化器或者便利初始化器开始调用。
·为类分配内存,但是这块内存还没初始化。
·指定初始化器确保该类的所有属性被初始化完成。
·调用父类的初始化方法初始父类的属性。
·整个初始化链条完成。阶段1完成。
阶段2:
在此阶段可以访问self,可以访问实例方法,进一步自定义属性,包括父类的属性。而便利初始化器也能进一步定制属性。

值类型的初始化会简单很多。因为没有继承。但是结构体会自动获得一个成员初始化器如果没有定义任何初始化器。而且值类型和类类型都会获得默认初始化器如果他们都没有定义任何初始化器。

接下来谈谈初始化器的继承。初始化器其实默认不会继承的。但是有以下规则。
1.子类没有实现任何初始化方法。会默认继承父类的指定初始化方法。2.子类如果继承或者实现了父类的所有指定初始化方法,则也会继承父类的便利初始化器。

初始化器虽然默认不会继承,但是自己实现父类的初始化器需要override。

甚至初始化器可以用init?或者init!指定有可能失败。而且任何初始化器可以内部都可以调用其它可能失败的初始化器(包括自己活着父类的,只是可能要强制解包)。

required关键字表明一个初始化器,必须被所有子类实现。而且你会在子类中再用required传递给所有子类必须实现。(当然通过自动继承可以省略实现)

可以用闭包来给一个存储属性赋予一个默认的属性值。

class SomeClass {
    let someProperty: SomeType = {
        // create a default value for someProperty inside this closure
        // someValue must be of the same type as SomeType
        return someValue
    }()
}

不要忘记结尾的括号。(如果没有括号则表明将一个闭包赋值给了一个存储属性。)
闭包内的代码会在实例初始化的时候执行,并赋予存储属性一个值。注意闭包内不能访问任何实例属性或者self或者实例方法因为此时还没初始化完成。

Web note ad 1