Initializer Delegation — это система делегирования инициализации, встроенная в Swift для классов. В Swift исторически сложилось различие между designated initializer (основной инициализатор класса, ответственный за полную инициализацию всех свойств) и convenience initializer (вспомогательный, облегчающий создание экземпляра с различными наборами параметров).
Проблема: если допустить хаотичное выполнение инициализаторов между классами и их наследниками, не исключена ситуация, когда базовый класс не будет до конца инициализирован, либо инициализация пройдет больше одного раза, что приведет к невалидному объекту.
Решение — строгое правило:
Пример кода:
class Vehicle { var wheels: Int // Designated initializer init(wheels: Int) { self.wheels = wheels } // Convenience initializer convenience init() { self.init(wheels: 4) } } class Car: Vehicle { var color: String // Designated initializer init(wheels: Int, color: String) { self.color = color super.init(wheels: wheels) } // Convenience initializer convenience init(color: String) { self.init(wheels: 4, color: color) } }
Ключевые особенности:
Вопрос 1: Может ли convenience initializer вызвать инициализатор суперкласса напрямую через super.init?
Нет, convenience initializer всегда делегирует инициализацию другому инициализатору текущего класса, который впоследствии может вызвать designated initializer суперкласса.
Вопрос 2: Что произойдет, если не реализовать required инициализатор в подклассе?
Если суперкласс имеет required инициализатор, то его обязательно нужно переопределить в каждом подклассе (используя required), иначе компилятор выдаст ошибку.
Вопрос 3: В чем отличие между convenience init и convenience required init?
convenience required init требуется, если конкретный convenience инициализатор объявлен как required в суперклассе для обеспечения поддержки инициализации в иерархиях наследования.
Разработчик вызвал super.init из convenience инициализатора. Код компилировался только благодаря отсутствию определённых ограничений, но в момент выполнения возникла ошибка: не все свойства объекта были инициализированы.
Плюсы:
Минусы:
Использовали четко структурированные designated и convenience инициализаторы с явным вызовом друг друга. Логика вызывалась строго по правилам Swift, поэтому инициализация была всегда прозрачной и корректной.
Плюсы:
Минусы: