À partir des documents
Contrôle de sécurité 1
Un initialiseur désigné doit s'assurer que toutes les propriétés introduites par sa classe sont initialisées avant de déléguer jusqu'à un initialiseur de superclasse.
Pourquoi avons-nous besoin d'un contrôle de sécurité comme celui-ci?
Pour répondre à cela, nous allons parcourir le processus d'initialisation en un rien de temps.
Initialisation en deux phases
L'initialisation de classe dans Swift est un processus en deux phases. Dans la première phase, chaque propriété stockée se voit attribuer une valeur initiale par la classe qui l'a introduite. Une fois que l'état initial de chaque propriété stockée a été déterminé, la deuxième phase commence et chaque classe a la possibilité de personnaliser davantage ses propriétés stockées avant que la nouvelle instance ne soit considérée comme prête à l'emploi.
L'utilisation d'un processus d'initialisation en deux phases rend l'initialisation sûre, tout en offrant une flexibilité complète à chaque classe dans une hiérarchie de classes. L'initialisation en deux phases empêche d'accéder aux valeurs de propriété avant qu'elles ne soient initialisées et empêche que les valeurs de propriété soient définies sur une valeur différente par un autre initialiseur de manière inattendue.
Donc, pour vous assurer que le processus d'initialisation en deux étapes est effectué comme défini ci-dessus, il y a quatre contrôles de sécurité, l'un d'eux est,
Contrôle de sécurité 1
Un initialiseur désigné doit s'assurer que toutes les propriétés introduites par sa classe sont initialisées avant de déléguer jusqu'à un initialiseur de superclasse.
Or, l'initialisation en deux phases ne parle jamais d'ordre, mais ce contrôle de sécurité, introduit super.init
à ordonner, après l'initialisation de toutes les propriétés.
Le contrôle de sécurité 1 peut sembler non pertinent, car l'
initialisation en deux phases empêche d'accéder aux valeurs des propriétés avant qu'elles ne soient initialisées , sans ce contrôle de sécurité 1.
Comme dans cet exemple
class Shape {
var name: String
var sides : Int
init(sides:Int, named: String) {
self.sides = sides
self.name = named
}
}
class Triangle: Shape {
var hypotenuse: Int
init(hypotenuse:Int) {
super.init(sides: 3, named: "Triangle")
self.hypotenuse = hypotenuse
}
}
Triangle.init
a initialisé, chaque propriété avant d'être utilisée. Donc, le contrôle de sécurité 1 ne semble pas pertinent,
Mais il pourrait y avoir un autre scénario, un peu complexe,
class Shape {
var name: String
var sides : Int
init(sides:Int, named: String) {
self.sides = sides
self.name = named
printShapeDescription()
}
func printShapeDescription() {
print("Shape Name :\(self.name)")
print("Sides :\(self.sides)")
}
}
class Triangle: Shape {
var hypotenuse: Int
init(hypotenuse:Int) {
self.hypotenuse = hypotenuse
super.init(sides: 3, named: "Triangle")
}
override func printShapeDescription() {
super.printShapeDescription()
print("Hypotenuse :\(self.hypotenuse)")
}
}
let triangle = Triangle(hypotenuse: 12)
Production :
Shape Name :Triangle
Sides :3
Hypotenuse :12
Ici, si nous avions appelé super.init
avant de définir le hypotenuse
, l' super.init
appel aurait alors appelé le printShapeDescription()
et puisque cela a été remplacé, il reviendrait d'abord à l'implémentation de la classe Triangle printShapeDescription()
. La printShapeDescription()
classe of Triangle accède à hypotenuse
une propriété non facultative qui n'a pas encore été initialisée. Et cela n'est pas autorisé car l' initialisation en deux phases empêche l'accès aux valeurs des propriétés avant leur initialisation
Assurez-vous donc que l'initialisation en deux phases se fait comme défini, il doit y avoir un ordre spécifique d'appel super.init
, et c'est-à-dire, après avoir initialisé toutes les propriétés introduites par self
classe, nous avons donc besoin d'un contrôle de sécurité 1