初始化方法永远遵循以下两个原则:
1.初始化路径必须保证对象完全初始化,这可以通过调用本类型的 designated 初始化方法来得到保证;
2.子类的 designated 初始化方法必须调用父类的 designated 方法,以保证父类也完成初始化。
对于某些我们希望子类中一定实现的 designated 初始化方法,我们可以通过添加 required 关键字进行限制,强制子类对这个方法重写实现。这样做的最大的好处是可以保证依赖于某个 designated 初始化方法的 convenience一直可以被使用。一个现成的例子就是上面的 init(bigNum: Bool):如果我们希望这个初始化方法对于子类一定可用,那么应当将 init(num: Int)声明为必须,这样我们在子类中调用 init(bigNum: Bool) 时就始终能够找到一条完全初始化的路径了:
class ClassA {
let numA: Int
required init(num: Int) {
numA = num
}
convenience init(bigNum: Bool) {
self.init(num: bigNum ? 10000 : 1)
}
}
class ClassB: ClassA {
let numB: Int
required init(num: Int) {
numB = num + 1
super.init(num: num)
}
}
不仅仅是对 designated 初始化方法,对于 convenience 的初始化方法,我们也可以加上 required以确保子类对其进行实现。这在要求子类不直接使用父类中的 convenience 初始化方法时会非常有帮助。