Aus den Dokumenten
Sicherheitsüberprüfung 1
Ein designierter Initialisierer muss sicherstellen, dass alle von seiner Klasse eingeführten Eigenschaften initialisiert werden, bevor er an einen Superklassen-Initialisierer delegiert.
Warum brauchen wir so eine Sicherheitsüberprüfung?
Um dies zu beantworten, lassen Sie uns den Initialisierungsprozess schnell durchlaufen.
Zweiphaseninitialisierung
Die Klasseninitialisierung in Swift ist ein zweiphasiger Prozess. In der ersten Phase wird jeder gespeicherten Eigenschaft von der Klasse, die sie eingeführt hat, ein Anfangswert zugewiesen. Sobald der Anfangszustand für jede gespeicherte Eigenschaft bestimmt wurde, beginnt die zweite Phase, und jede Klasse hat die Möglichkeit, ihre gespeicherten Eigenschaften weiter anzupassen, bevor die neue Instanz als einsatzbereit betrachtet wird.
Die Verwendung eines zweiphasigen Initialisierungsprozesses macht die Initialisierung sicher und bietet gleichzeitig jeder Klasse in einer Klassenhierarchie vollständige Flexibilität. Die zweiphasige Initialisierung verhindert, dass auf Eigenschaftswerte zugegriffen wird, bevor sie initialisiert werden , und verhindert, dass Eigenschaftswerte von einem anderen Initialisierer unerwartet auf einen anderen Wert gesetzt werden.
Um sicherzustellen, dass der zweistufige Initialisierungsprozess wie oben definiert durchgeführt wird, gibt es vier Sicherheitsüberprüfungen. Eine davon ist:
Sicherheitsüberprüfung 1
Ein designierter Initialisierer muss sicherstellen, dass alle von seiner Klasse eingeführten Eigenschaften initialisiert werden, bevor er an einen Superklassen-Initialisierer delegiert.
Bei der zweiphasigen Initialisierung geht es nie um die Reihenfolge, aber diese Sicherheitsüberprüfung führt super.init
dazu, dass nach der Initialisierung aller Eigenschaften eine Bestellung durchgeführt wird.
Die Sicherheitsüberprüfung 1 scheint irrelevant zu sein, da die
zweiphasige Initialisierung verhindert, dass auf Eigenschaftswerte zugegriffen werden kann, bevor sie initialisiert werden, ohne diese Sicherheitsüberprüfung 1 erfüllt werden kann.
Wie in diesem Beispiel
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
hat jede Eigenschaft vor der Verwendung initialisiert. Sicherheitscheck 1 scheint also irrelevant,
Aber dann könnte es ein anderes Szenario geben, ein bisschen komplex,
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)
Ausgabe :
Shape Name :Triangle
Sides :3
Hypotenuse :12
Wenn wir das super.init
vor dem Setzen des aufgerufen hätten hypotenuse
, hätte der super.init
Aufruf dann das aufgerufen, printShapeDescription()
und da dies überschrieben wurde, würde er zuerst auf die Implementierung der Triangle-Klasse von zurückgreifen printShapeDescription()
. Die printShapeDescription()
of Triangle-Klasse greift auf hypotenuse
eine nicht optionale Eigenschaft zu, die noch nicht initialisiert wurde. Dies ist nicht zulässig, da durch die zweiphasige Initialisierung verhindert wird, dass auf Eigenschaftswerte zugegriffen wird, bevor sie initialisiert werden
Stellen Sie also sicher, dass die Zwei-Phasen-Initialisierung wie definiert durchgeführt wird. Es muss eine bestimmte super.init
Aufrufreihenfolge geben. Nach der Initialisierung aller von der self
Klasse eingeführten Eigenschaften benötigen wir daher eine Sicherheitsüberprüfung 1