Ответ
Правило: Designated (назначенный) инициализатор обязан вызвать designated инициализатор своего непосредственного суперкласса.
Пример иерархии:
class Vehicle {
var numberOfWheels: Int
// Designated инициализатор базового класса
init(wheels: Int) {
self.numberOfWheels = wheels
}
}
class Bicycle: Vehicle {
var hasBell: Bool
// Designated инициализатор подкласса
init(hasBell: Bool) {
// 1. Сначала инициализируем ВСЕ свойства своего класса
self.hasBell = hasBell
// 2. Затем вызываем designated инициализатор суперкласса
super.init(wheels: 2) // Обязательный вызов
}
}
// Convenience инициализатор в конечном счете вызывает designated своего класса
class Car: Vehicle {
var brand: String
init(brand: String, wheels: Int) { // Designated
self.brand = brand
super.init(wheels: wheels)
}
convenience init(brand: String) { // Convenience
// Должен в итоге вызвать designated своего класса
self.init(brand: brand, wheels: 4)
}
}
Ключевые моменты:
- Порядок: Сначала инициализируются все свойства текущего класса, только потом — вызов
super.init(...). - Нарушение правила приводит к ошибке компиляции.
- Convenience инициализаторы вызывают другие инициализаторы того же класса (в итоге цепочка доходит до designated).