In Swift müssen alle Eigenschaften vom Typ non-optional vor Abschluss der Instanziierung eines Objekts initialisiert werden. Dafür werden Initialisierer verwendet: designated (grundlegend), convenience (hilfreich) und required (für Nachfolger erforderlich).
Beispiel:
class Vehicle { let numberOfWheels: Int required init(numberOfWheels: Int) { self.numberOfWheels = numberOfWheels } } class Car: Vehicle { let brand: String // Designated Initializer required init(numberOfWheels: Int) { self.brand = "Unknown" super.init(numberOfWheels: numberOfWheels) } // Convenience convenience init() { self.init(numberOfWheels: 4) self.brand = "Ford" } }
Wichtige Merkmale:
In welcher Reihenfolge sollten die Eigenschaften der Unterklasse und der Superklasse bei der Verwendung des designated Initialisierers initialisiert werden?
Antwort: Alle Eigenschaften der Unterklasse müssen vor dem Aufruf des designated Initialisierers der Superklasse (super.init) initialisiert werden, andernfalls gibt es einen Kompilierungsfehler. Nach super.init dürfen keine neuen stored-Eigenschaften der Unterklasse mehr initialisiert werden, sondern nur verwendet werden.
class Parent { let parentProp: Int init(prop: Int) { parentProp = prop } } class Child: Parent { let childProp: String init(prop: Int, childProp: String) { self.childProp = childProp // Zuerst eigene Eigenschaften super.init(prop: prop) // Dann parent } }
Geschichte
Ein Entwickler versuchte in einem convenience Initialisierer, direkt einen Wert für eine required-Eigenschaft zuzuweisen, ohne den designated Initialisierer aufzurufen. Infolgedessen wurde die Eigenschaft zweimal mit unterschiedlichen Werten initialisiert, was während des Testens zu unerwartetem Verhalten führte.
Geschichte
Bei der Vererbung einer tiefen Klassenhierarchie wurde vergessen, den required init zu deklarieren, was zu einer nicht korrekten Initialisierung des abgeleiteten Typs aus dem Framework über Reflection führte und zu einem Absturz bei der Deserialisierung des JSON-Modells.
Geschichte
Während der Erweiterung der Klasse Vehicle wurde der designated Initialisierer der Superklasse nicht aufgerufen, was zu einer inkorrekten Initialisierung der erforderlichen Eigenschaften und einem Laufzeitabsturz in der Produktion nach dem Update des Datenschemas führte.