En Swift, toutes les propriétés de types non-optionnels doivent être initialisées avant la fin de l'initialisation d'une instance. Pour cela, on utilise des initialisateurs : designated (principaux), convenience (secondaires) et required (obligatoires pour les sous-classes).
Exemple :
class Vehicle { let numberOfWheels: Int required init(numberOfWheels: Int) { self.numberOfWheels = numberOfWheels } } class Car: Vehicle { let brand: String // Initialiseur designated required init(numberOfWheels: Int) { self.brand = "Unknown" super.init(numberOfWheels: numberOfWheels) } // Convenience convenience init() { self.init(numberOfWheels: 4) self.brand = "Ford" } }
Caractéristiques clés :
Dans quel ordre doit-on initialiser les propriétés de la sous-classe et de la super-classe lors de l'utilisation d'un initialiseur designated ?
Réponse : Toutes les propriétés de la sous-classe doivent être initialisées avant d'appeler l'initialiseur designated de la super-classe (super.init), sinon il y aura une erreur de compilation. Après super.init, il n'est pas possible d'initialiser de nouvelles propriétés stockées de la sous-classe, uniquement de les utiliser.
class Parent { let parentProp: Int init(prop: Int) { parentProp = prop } } class Child: Parent { let childProp: String init(prop: Int, childProp: String) { self.childProp = childProp // D'abord ses propres propriétés super.init(prop: prop) // Ensuite parent } }
Histoire
Un développeur dans l'initialiseur convenience a essayé d'assigner directement une valeur à une propriété required sans appeler designated. En conséquence, la propriété a été initialisée deux fois avec des valeurs différentes, entraînant un comportement inattendu lors des tests.
Histoire
Lors de l'héritage d'une hiérarchie de classes profonde, on a oublié de déclarer required init, ce qui a rendu impossible l'initialisation correcte du type dérivé depuis un framework via reflection, entraînant un crash lors de la désérialisation d'un modèle JSON.
Histoire
Dans l'application, lors de l'extension de la classe Vehicle, l'initialiseur designated de la super-classe n'a pas été appelé, ce qui a entraîné une initialisation incorrecte des propriétés obligatoires et un crash runtime en production après la mise à jour du schéma de données.