Z dokumentów
Kontrola bezpieczeństwa 1
Wyznaczony inicjalizator musi zapewnić, że wszystkie właściwości wprowadzone przez jego klasę zostaną zainicjowane przed delegowaniem do inicjalizatora nadklasy.
Dlaczego potrzebujemy takiej kontroli bezpieczeństwa?
Aby odpowiedzieć na to, przejdźmy szybko przez proces inicjalizacji.
Inicjalizacja dwufazowa
Inicjalizacja klasy w Swift jest procesem dwufazowym. W pierwszej fazie każdej przechowywanej właściwości przypisywana jest klasa początkowa przez klasę, która ją wprowadziła. Po określeniu stanu początkowego dla każdej przechowywanej właściwości rozpoczyna się druga faza i każda klasa ma możliwość dalszego dostosowania swoich przechowywanych właściwości, zanim nowa instancja zostanie uznana za gotową do użycia.
Zastosowanie dwufazowego procesu inicjalizacji sprawia, że inicjalizacja jest bezpieczna, a jednocześnie zapewnia pełną elastyczność każdej klasie w hierarchii klas. Inicjalizacja dwufazowa uniemożliwia dostęp do wartości właściwości przed ich zainicjowaniem i zapobiega nieoczekiwanemu ustawieniu wartości właściwości na inną wartość przez inny inicjator.
Tak więc, aby upewnić się, że dwuetapowy proces inicjalizacji przebiega zgodnie z powyższą definicją, istnieją cztery kontrole bezpieczeństwa, jednym z nich jest
Kontrola bezpieczeństwa 1
Wyznaczony inicjalizator musi zapewnić, że wszystkie właściwości wprowadzone przez jego klasę zostaną zainicjowane przed delegowaniem do inicjalizatora nadklasy.
Teraz dwufazowa inicjalizacja nigdy nie mówi o kolejności, ale ta kontrola bezpieczeństwa wprowadza się super.init
po zamówieniu, po inicjalizacji wszystkich właściwości.
Kontrola bezpieczeństwa 1 może wydawać się nieistotna, ponieważ
inicjalizacja dwufazowa uniemożliwia dostęp do wartości właściwości przed ich zainicjowaniem , bez tej kontroli bezpieczeństwa 1.
Jak w tej próbce
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
zainicjował każdą właściwość przed użyciem. Kontrola bezpieczeństwa 1 wydaje się nieistotna,
Ale potem może być inny scenariusz, trochę skomplikowany,
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)
Wynik :
Shape Name :Triangle
Sides :3
Hypotenuse :12
Tutaj, gdybyśmy wywołali super.init
przed ustawieniem hypotenuse
, super.init
wywołanie wywołałoby wtedy printShapeDescription()
i, ponieważ zostało to nadpisane, najpierw powróciłoby do implementacji klasy Trójkąta printShapeDescription()
. printShapeDescription()
Triangle dostępu klasowym hypotenuse
niebędącego własnością opcjonalne, które wciąż nie zostały zainicjowane zostały. Nie jest to dozwolone, ponieważ inicjalizacja dwufazowa uniemożliwia dostęp do wartości właściwości przed ich zainicjowaniem
Upewnij się więc, że inicjalizacja dwufazowa przebiega zgodnie z definicją, musi istnieć konkretna kolejność wywoływania super.init
, to znaczy po zainicjowaniu wszystkich właściwości wprowadzonych przez self
klasę, dlatego potrzebujemy kontroli bezpieczeństwa 1