В действительности наличие двух ваших инициализаторов - это Bad Code ™. Как сказал Лео Дабус, express точный пример, использующий наиболее подходящую языковую функцию 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
)
}
… или использовать один назначенный инициализатор, который фактически выполняет работать и переслать требуемый init вместе с ним:
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
)
}
Мне трудно найти хороший пример, где удобный инициализатор - единственный способ выполнить sh создание конкретного экземпляра класс, который не может быть выполнен вторым инициализатором, как я делал в первом примере.
Вы всегда можете дублировать код. Удобный инициализатор никогда не будет единственным способом. В самых простых случаях, как я показываю здесь, у вас будет только частичная строка дублирования для каждого инициализатора. Это не имеет большого значения. Но дедупликация накапливается с наследованием.
Если ваш подкласс обеспечивает реализацию всех своих инициализаторов, назначенных суперклассом, - либо наследуя их согласно правилу 1, либо предоставляя пользовательскую реализацию как часть его определение - тогда он автоматически наследует все удобные инициализаторы суперкласса. - https://docs.swift.org/swift-book/LanguageGuide/Initialization.html
Так, например, когда вы используете удобную + назначенную комбо, вы можете пропустить переписывание требуемого инициала.
например
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 преобразуйте обозначенные инициализаторы в вспомогательные в подклассах.) Вам придется поддерживать меньше кода.