构造过程是在创建一个类或结构体的新实例时所执行的一系列初始化步骤。构造器是用于此类初始化过程的特殊方法。在 Swift 中,构造器不返回任何值,并且主要任务是保证新实例在第一次使用之前其所有存储属性都已设置为合适的初始值。此外,构造器还可以设置其他指定的配置,例如设置默认值、创建常量属性等。
实例属性的初始化
在实例被创建时,其所有的存储属性必须有确定的初始值。这意味着每个存储属性要么在声明时就有一个默认值,要么在实例构造过程中被赋予一个初始值。
默认初始化
对于简单的结构体和类,Swift 提供了一种简洁的方式来自动地为所有存储属性提供默认值。例如:
struct Point {
var x = 0.0, y = 0.0
}
var point = Point() // 点 (0.0, 0.0)在这个例子中,Point 结构体有两个存储属性 x 和 y,它们都有默认值 0.0。因此,在创建一个新的 Point 实例时,无需显式地为这两个属性赋值。
手动初始化
对于更复杂的情况,你可能需要手动为存储属性设置初始值。这通常在自定义构造器中完成:
// www.javascriptcn.com code example
struct Size {
var width = 0.0, height = 0.0
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}
var size = Size(width: 20.0, height: 50.0) // 大小 (20.0, 50.0)在这个例子中,我们定义了一个名为 Size 的结构体,它具有一个定制的构造器来接受宽度和高度作为参数。
初始化阶段的顺序
Swift 在构造过程中遵循一套严格的规则,确保所有存储属性都被正确地初始化。这些规则包括但不限于:
- 每个存储属性必须在构造器结束之前被赋予一个初始值。
- 如果子类继承了父类,则子类的构造器必须调用父类的构造器。
- 子类可以在自己的构造器中对父类的属性进行修改,但在父类构造器完成之前不能访问它们。
调用父类构造器
当创建一个子类实例时,你需要确保所有超类的存储属性都在子类构造器完成之前被正确初始化。为此,你需要在子类构造器中调用父类构造器:
// www.javascriptcn.com code example
class Circle {
var radius: Double
init(radius: Double) {
self.radius = radius
}
}
class Wheel: Circle {
var numberOfSpokes: Int
init(radius: Double, numberOfSpokes: Int) {
self.numberOfSpokes = numberOfSpokes
super.init(radius: radius) // 调用父类构造器
}
}
let wheel = Wheel(radius: 0.6, numberOfSpokes: 10)在这个例子中,Wheel 类继承自 Circle 类。在 Wheel 的构造器中,首先初始化了 numberOfSpokes 属性,然后调用了父类 Circle 的构造器来初始化 radius 属性。
自定义构造过程
除了上述标准构造器之外,Swift 还提供了几种额外的构造方式,比如反向构造器(deinitializers)、可失败构造器(failable initializers)以及便利构造器(convenience initializers)等。
可失败构造器
有时候,构造过程可能会因为某些原因而无法成功。Swift 提供了可失败构造器来处理这种情况。通过将构造器标记为可失败,可以指定如果初始化失败则返回 nil:
// www.javascriptcn.com code example
struct Person {
let name: String
init?(name: String) {
if name.isEmpty { return nil } // 如果名字为空,则构造失败
self.name = name
}
}
let person = Person(name: "Alice") // 成功
let emptyPerson = Person(name: "") // 失败在这个例子中,Person 结构体有一个可失败构造器,它检查传入的名字是否为空。如果为空,则构造失败并返回 nil。
便利构造器
便利构造器是一种特殊的构造器,它提供了一种更灵活的方式来创建实例。便利构造器通常会调用同一个类中的另一个构造器,或者通过调用父类构造器来简化实例的创建过程:
// www.javascriptcn.com code example
class Car {
let model: String
init(model: String) {
self.model = model
}
convenience init() {
self.init(model: "Unknown") // 调用主构造器
}
}
let car1 = Car(model: "Tesla")
let car2 = Car() // 使用便利构造器在这个例子中,Car 类有一个主构造器和一个便利构造器。便利构造器调用了主构造器,并提供了一个默认的模型名称。
通过理解并应用这些构造过程的概念和技术,你可以更加灵活和有效地管理你的 Swift 类和结构体的初始化逻辑。