事实上,拥有两个初始化程序是 Bad Code™。正如 Leo Dabus 所说,使用最合适的 Swift 语言特性来表达该确切示例的方法是使用默认参数值。
class Person1 {
var name: String
var age: Int
var nationality: String
init(
name: String,
age: Int,
nationality: String = "Canadian"
) {
self.name = name
self.age = age
self.nationality = nationality
}
}
便利初始化器是在存在另一个初始化器时使用的,它将为您节省代码重复。
例如,假设您添加了一个超类,并带有必需的 init:
class Person0 {
var name: String
var age: Int
required init(
name: String,
age: Int
) {
self.name = name
self.age = age
}
}
你不能只这样做;Swift 认为这不能满足要求:
class Person1: Person0 {
var nationality: String
required init(
name: String,
age: Int,
nationality: String = "Canadian"
) {
self.nationality = nationality
super.init(
name: name,
age: age
)
}
}
相反,您可以复制,如下所示:
required init(
name: String,
age: Int
) {
nationality = "Canadian"
super.init(
name: name,
age: age
)
}
init(
name: String,
age: Int,
nationality: String
) {
self.nationality = nationality
super.init(
name: name,
age: age
)
}
…或者使用一个指定的初始化器,它实际上完成了工作,并将所需的初始化器转发给它:
required convenience init(
name: String,
age: Int
) {
self.init(
name: name,
age: age,
nationality: "Canadian"
)
}
init(
name: String,
age: Int,
nationality: String
) {
self.nationality = nationality
super.init(
name: name,
age: age
)
}
我发现很难找到一个好的示例,其中便利初始化程序是完成创建类的特定实例的唯一方法,而第二个初始化程序无法像我在第一个示例中所做的那样完成。
你总是可以复制代码。便利初始化器永远不会是唯一的方法。在最简单的情况下,就像我在这里展示的那样,每个初始值设定项只会有部分重复行。这没什么大不了的。但是重复数据删除会随着继承而堆积起来。
如果您的子类提供了其所有超类指定初始化器的实现(通过按照规则 1 继承它们,或者通过提供自定义实现作为其定义的一部分),那么它会自动继承所有超类便利初始化器。– https://docs.swift.org/swift-book/LanguageGuide/Initialization.html
因此,例如,当您使用便利 + 指定组合时,您可以跳过重写所需的 init。
例如
Person2(name: "Terrance Phillip", age: 42)
编译,从这里:
class Person2: Person1 {
var flag: String
override convenience init(
name: String,
age: Int,
nationality: String
) {
self.init(
name: name,
age: age,
nationality: nationality,
flag: ""
)
}
init(
name: String,
age: Int,
nationality: String,
flag: String
) {
self.flag = flag
super.init(
name: name,
age: age,
nationality: nationality
)
}
}
和这个人也是同一个人:
Person3()
…鉴于这种:
class Person3: Person2 {
convenience init() {
self.init(
name: "Terrance Phillip",
age: 42
)
}
}
作为指导,尽可能使用 1. 默认参数和 2. 便利初始化器。(并且作为 2 的扩展,在子类中将指定的初始化程序转换为方便的初始化程序。)您将需要维护更少的代码。