在上一篇博客中简介了构造器基础层面的知识构造器(一),以下我们深入的学习类的构造器应用。
在Swift中类一共同拥有两种构造器:
- 指定构造器
- 便利构造器
什么是指定构造器,有什么作用?
我个人的理解为在类中没有加不论什么keyword的构造器称为指定构造器。作用为初始化类中全部的实例存储属性
init()
{
...
}
什么是便利构造器,有什么作用?
我个人理解为在类中(仅仅能在类中,结构体和枚举里面是没有的)加上conveniencekeyword的构造器为便利构造器,作用为辅助性调用指定构造器进行一系列的工作。感觉体现了在Object-C中的代理模式。
convenience init()
{
...
//注意这里必须调用同一类的其它构造器,这里调用的能够是其它便利构造器或者是指定构造器
}
综合的看一个励志吧,请原谅程序猿的屌丝:
class Man
{
var say:String
init(say:String)
{
self.say=say
}
convenience init(Say:String)
{
self.init(say:Say)
}
}
var man1=Man(say: "我喜欢你!")
print(man1.say)
var man2=Man(Say: "啊,不,我不喜欢你!我爱你!
")
print(man2.say)
构造器的调用链遵守三条规则
- 子类构造器必须调用直接父类的指定构造器
- 便利构造器必须调用同一类中的其它构造器
- 便利构造器调用的构造器的终点必须是指定构造器
类构造的两个阶段:
第一阶段:
程序调用子类的某个构造器
为实例分配内存, 此时实例的内存还没有被初始化
指定构造器确保子类定义的全部实例存储属性都已被赋初值
指定构造器将调用父类的构造器, 完毕父类定义的实例存储属性的初始化
沿着调用父类构造器的构造器链一直往上运行, 直到到达构造器链的最顶部
第二阶段:
沿着继承树往下, 构造器此时能够改动实例属性和訪问self, 甚至能够调用实例方法
最后, 构造器链中的便利构造器都有机会定制实例和使用self
Swift安全检查
安全检查1:指定构造器必须先初始化当前类中定义的实例存储属性, 然后才干向上调用父类构造器
安全检查2:指定构造器必须向上调用父类构造器, 然后才干对继承得到的属性赋值
安全检查3:便利构造器必须先调用同一个类的其它构造器, 然后才干对属性赋值
安全检查4:构造器在第一阶段完毕之前, 不能调用实例方法, 不能读取实例属性
class Person { var name: String! var weight: Double // 定义指定构造器 init(name: String, weight: Double) { self.name = name self.weight = weight } // 定义便利构造器(使用convenience修饰) convenience init(n name: String, w weight: Double) { self.init(name: name, weight: weight) }
}
class Man: Person { var sex: String! init(sex: String, name: String, weight: Double) { // print(super.name) 不能再父类初始化之前调用父类中的属性 super.init(name: name, weight: weight) super.name = "lala" print(self.name) // print(self.sex) 不能在本类中的属性没有进行初始化的时候进行调用 // 会出现:fatal error: unexpectedly found nil while unwrapping an Optional value错误 self.sex = sex print(self.sex) } convenience init(s sex: String, n name: String, weight: Double) { // 在调用其它构造器之前, 不能訪问或改动不论什么实例存储属性 // print(self.name) 错误 // super.name = name 错误 self.init(sex: sex, name: name, weight: weight) } } var man = Man(sex: "男", name: "Rinpe", weight: 62.0)