Initializer Delegation ist ein in Swift für Klassen eingebautes System zur Delegierung der Initialisierung. In Swift gibt es historisch gesehen einen Unterschied zwischen designated initializer (der Hauptinitialisierer einer Klasse, der für die vollständige Initialisierung aller Eigenschaften verantwortlich ist) und convenience initializer (ein Hilfsinitialisierer, der das Erstellen einer Instanz mit verschiedenen Parameter-Sets erleichtert).
Problem: Wenn die Initialisierer zwischen Klassen und ihren Nachkommen chaotisch ausgeführt werden, kann es passieren, dass die Basisklasse nicht vollständig initialisiert wird oder die Initialisierung mehr als einmal durchgeführt wird, was zu einem ungültigen Objekt führt.
Die Lösung ist eine strenge Regel:
Beispielcode:
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) } }
Hauptmerkmale:
Frage 1: Kann der convenience Initializer den Initializer der Superklasse direkt über super.init aufrufen?
Nein, der convenience Initializer delegiert immer die Initialisierung an einen anderen Initializer der aktuellen Klasse, der anschließend den designated Initializer der Superklasse aufrufen kann.
Frage 2: Was passiert, wenn der required Initializer nicht im Unterklasse implementiert wird?
Wenn die Superklasse einen required Initializer hat, muss dieser unbedingt in jeder Unterklasse (unter Verwendung von required) überschrieben werden, andernfalls gibt der Compiler einen Fehler aus.
Frage 3: Was ist der Unterschied zwischen convenience init und convenience required init?
convenience required init ist erforderlich, wenn der spezifische convenience Initializer im Superklasse als required deklariert wird, um die Unterstützung der Initialisierung in Vererbungshierarchien zu gewährleisten.
Ein Entwickler hat super.init aus dem convenience Initializer aufgerufen. Der Code wurde nur aufgrund des Fehlens bestimmter Einschränkungen kompiliert, aber zur Laufzeit trat ein Fehler auf: nicht alle Eigenschaften des Objekts waren initialisiert.
Vorteile:
Nachteile:
Es wurden klar strukturierte designated und convenience Initializer mit explizitem Aufruf voneinander verwendet. Die Logik wurde streng nach den Regeln von Swift aufgerufen, daher war die Initialisierung immer transparent und korrekt.
Vorteile:
Nachteile: