在Swift中,所有非可选类型的属性必须在实例初始化结束之前进行初始化。为此使用了初始化器:designated(指定),convenience(便利)和required(必须的)。
示例:
class Vehicle { let numberOfWheels: Int required init(numberOfWheels: Int) { self.numberOfWheels = numberOfWheels } } class Car: Vehicle { let brand: String // Designated 初始化器 required init(numberOfWheels: Int) { self.brand = "Unknown" super.init(numberOfWheels: numberOfWheels) } // Convenience convenience init() { self.init(numberOfWheels: 4) self.brand = "Ford" } }
关键特性:
在使用designated初始化器时,子类和超类的属性应按什么顺序初始化?
回答: 所有子类的属性必须在调用超类的designated初始化器(super.init)之前初始化,否则会导致编译错误。在super.init之后无法初始化子类的新存储属性,只能使用它们。
class Parent { let parentProp: Int init(prop: Int) { parentProp = prop } } class Child: Parent { let childProp: String init(prop: Int, childProp: String) { self.childProp = childProp // 首先初始化自己的属性 super.init(prop: prop) // 然后parent } }
故事
开发人员在便利初始化器中尝试直接给require属性赋值,而未调用designated。结果该属性被初始化了两次,赋予了不同的值,导致测试时出现意外行为。
故事
在深层类层次结构中继承时忘记声明required init,导致无法通过反射正确初始化框架中的派生类型,并在反序列化JSON模型时崩溃。
故事
在扩展Vehicle类时,未调用超类的designated初始化器,导致必需属性的初始化不正确,并在数据模式更新后在生产环境中崩溃。