5月27日 11:52

Swift 初始化器有哪些?指定初始化器和便利初始化器有什么区别?

Swift 有三种初始化器:指定初始化器(designated,负责初始化所有属性)、便利初始化器(convenience,调用其他初始化器的快捷方式)、可失败初始化器(init?,参数无效时返回 nil)。

指定初始化器是"主力"——必须初始化类引入的所有属性,然后调用父类的指定初始化器。便利初始化器是"辅助"——必须调用同类的另一个初始化器,最终链到指定初始化器。规则简单:便利调便利或指定,指定调父类指定。

追问

便利初始化器能调用父类的初始化器吗?

不能。便利初始化器必须调用同类的初始化器(self.init),不能直接调 super.init。这是 Swift 初始化安全链的保证——所有初始化路径最终都经过指定初始化器。如果子类需要父类的初始化器,编译器会自动继承(条件是子类没有自定义指定初始化器)。

可失败初始化器 init? 和 init! 有什么区别?

init? 返回 Optional,调用方得到 Type? 必须解包。init! 返回隐式解包 Optional,调用方直接用,nil 时崩溃。init! 基本只用于兼容 Objective-C 的初始化器——ObjC 的 init 返回 nil 表示失败,映射到 Swift 就是 init!。新代码用 init?。

结构体的初始化器和类有什么区别?

结构体没有指定/便利之分——所有初始化器地位平等。编译器自动合成成员初始化器(前提是没有自定义 init)。类没有自动合成的成员初始化器(除非所有属性有默认值且没有父类)。结构体的 init 不需要调用 super.init(没有继承)。

初始化器什么时候能访问 self?

类:指定初始化器在调用 super.init 之后(父类初始化完成),便利初始化器在调用 self.init 之后。结构体:所有存储属性初始化之后。在此之前访问 self 会编译报错——因为 self 还没完全构造。

required init 是什么?

标记 required 的初始化器,子类必须实现。典型场景:NSCoding 的 init(coder:)——如果子类不实现,反序列化会崩溃。required 保证了继承链上每个类都能响应这个初始化器。子类实现 required init 时不需要 override 关键字(因为不是重写,是满足协议要求)。

写段代码

swift
class Vehicle { var wheels: Int init(wheels: Int) { self.wheels = wheels } // 指定初始化器 } class Car: Vehicle { var brand: String init(brand: String, wheels: Int) { // 指定初始化器 self.brand = brand super.init(wheels: wheels) } convenience init(brand: String) { // 便利初始化器 self.init(brand: brand, wheels: 4) } } // 可失败初始化器 struct Temperature { let celsius: Double init?(celsius: Double) { guard celsius >= -273.15 else { return nil } self.celsius = celsius } } if let temp = Temperature(celsius: -300) { print(temp) // 不会执行,nil }
标签:Swift