Ответ
convenience — обозначает вспомогательный (вторичный) инициализатор, который должен внутри вызвать designated (назначенный) инициализатор того же класса. Упрощает создание объекта с альтернативными параметрами или значениями по умолчанию.
required — обязывает все прямые подклассы реализовать данный инициализатор. Гарантирует, что определённая логика инициализации будет доступна во всей иерархии наследования.
Основные отличия:
convenience |
required |
|
|---|---|---|
| Назначение | Упрощение инициализации | Контракт для подклассов |
| Вызов | Должен вызвать self.init |
Может быть как designated, так и convenience |
| Наследование | Может быть переопределён в подклассе | Обязателен для реализации в подклассе |
| Использование | Альтернативные параметры, значения по умолчанию | Протоколы, классовые типы, фабричные методы |
Пример convenience инициализатора:
class Document {
var title: String
var body: String
// Designated инициализатор
init(title: String, body: String) {
self.title = title
self.body = body
}
// Convenience инициализатор
convenience init(title: String) {
self.init(title: title, body: "") // Вызов designated
}
// Ещё один convenience
convenience init() {
self.init(title: "Untitled") // Вызов другого convenience
}
}
let doc1 = Document(title: "Report", body: "Content") // Designated
let doc2 = Document(title: "Note") // Convenience
let doc3 = Document() // Convenience -> Convenience -> Designated
Пример required инициализатора:
class Vehicle {
let wheels: Int
// Все подклассы должны реализовать этот init
required init(wheels: Int) {
self.wheels = wheels
}
}
class Car: Vehicle {
let brand: String
init(brand: String) {
self.brand = brand
super.init(wheels: 4)
}
// Обязательная реализация required инициализатора
required init(wheels: Int) {
self.brand = "Unknown"
super.init(wheels: wheels)
}
}
class Bicycle: Vehicle {
// Тоже должен реализовать required init
required init(wheels: Int) {
super.init(wheels: wheels)
}
}
// Использование с классовой переменной (метаклассом)
func createVehicle(ofType type: Vehicle.Type) -> Vehicle {
return type.init(wheels: 2) // Требуется required init
}
let bike = createVehicle(ofType: Bicycle.self)
Важно:
convenienceинициализатор не может вызвать другойconvenienceинициализатор суперкласса, толькоdesignated.requiredмодификатор часто сочетается сconvenience, если нужен фабричный метод в иерархии.- При переопределении
requiredинициализатора в подклассе также нужно указыватьrequired(а неoverride).