Delegacja Inicjalizatora to system delegacji inicjalizacji wbudowany w Swift dla klas. W Swift historycznie istnieje rozróżnienie między designated initializer (główny inicjalizator klasy, odpowiedzialny za pełną inicjalizację wszystkich właściwości) a convenience initializer (wspomagający, ułatwiający tworzenie instancji z różnymi zestawami parametrów).
Problem: jeśli dopuścić do chaotycznego wykonywania inicjalizatorów między klasami a ich dziedzicami, istnieje ryzyko, że klasa bazowa nie będzie w pełni zainicjalizowana, lub inicjalizacja odbędzie się więcej niż raz, co doprowadzi do nieprawidłowego obiektu.
Rozwiązanie - ścisła zasada:
Przykład kodu:
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) } }
Kluczowe cechy:
Pytanie 1: Czy convenience initializer może bezpośrednio wywołać inicjalizator klasy bazowej przez super.init?
Nie, convenience initializer zawsze deleguje inicjalizację do innego inicjalizatora bieżącej klasy, który później może wywołać designated initializer klasy bazowej.
Pytanie 2: Co się stanie, jeśli nie zaimplementujemy required inicjalizatora w podklasie?
Jeśli klasa bazowa ma required inicjalizator, musi być on koniecznie nadpisany w każdej podklasie (z użyciem required), w przeciwnym razie kompilator zgłosi błąd.
Pytanie 3: Jaka jest różnica między convenience init a convenience required init?
convenience required init jest wymagany, jeśli dany convenience inicjalizator jest zadeklarowany jako required w klasie bazowej dla zapewnienia wsparcia dla inicjalizacji w hierarchiach dziedziczenia.
Programista wywołał super.init z convenience inicjalizatora. Kod kompilował się tylko dzięki braku określonych ograniczeń, jednak w momencie wykonywania wystąpił błąd: nie wszystkie właściwości obiektu były zainicjalizowane.
Zalety:
Wady:
Użyto jasno zdefiniowanych designated i convenience inicjalizatorów z wyraźnym wywołaniem jedne drugiego. Logika była wywoływana ściśle według zasad Swift, dlatego inicjalizacja była zawsze przejrzysta i poprawna.
Zalety:
Wady: