编程高级iOS开发者

如何在Swift中实现属性初始化?designated,convenience和required初始化器有什么区别?在处理初始化层次结构时会出现哪些注意事项?

用 Hintsage AI 助手通过面试

回答。

在Swift中,所有非可选类型的属性必须在实例初始化结束之前进行初始化。为此使用了初始化器:designated(指定),convenience(便利)和required(必须的)。

  • Designated 初始化器 — 主要的,负责初始化所有类的属性并调用超类的designated初始化器。每个类至少有一个designated初始化器。
  • Convenience 初始化器 — 便利的,委托该类的初始化(通过self.init(...)调用类中的其他初始化器),简化使用不同参数集创建对象的过程。
  • Required 初始化器 — 要求所有子类实现该初始化器。用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" } }

关键特性:

  • 所有属性必须在调用super.init之前初始化。
  • Convenience初始化器必须始终调用designated或其他便利初始化器self。
  • Required初始化器必须在所有子类中实现。

反问。

在使用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初始化器,导致必需属性的初始化不正确,并在数据模式更新后在生产环境中崩溃。