De los documentos
Control de seguridad 1
Un inicializador designado debe asegurarse de que todas las propiedades introducidas por su clase se inicialicen antes de delegar en un inicializador de superclase.
¿Por qué necesitamos un control de seguridad como este?
Para responder esto, avancemos rápidamente el proceso de inicialización.
Inicialización de dos fases
La inicialización de clases en Swift es un proceso de dos fases. En la primera fase, a cada propiedad almacenada se le asigna un valor inicial por la clase que la introdujo. Una vez que se ha determinado el estado inicial de cada propiedad almacenada, comienza la segunda fase, y cada clase tiene la oportunidad de personalizar aún más sus propiedades almacenadas antes de que la nueva instancia se considere lista para usar.
El uso de un proceso de inicialización de dos fases hace que la inicialización sea segura, a la vez que brinda flexibilidad total a cada clase en una jerarquía de clases. La inicialización en dos fases evita que se acceda a los valores de las propiedades antes de que se inicialicen , y evita que los valores de las propiedades sean configurados inesperadamente por otro inicializador.
Entonces, para asegurarse de que el proceso de inicialización de dos pasos se realice como se definió anteriormente, hay cuatro controles de seguridad, uno de ellos es,
Control de seguridad 1
Un inicializador designado debe asegurarse de que todas las propiedades introducidas por su clase se inicialicen antes de delegar en un inicializador de superclase.
Ahora, la inicialización de dos fases nunca habla del orden, pero este control de seguridad, se introduce super.init
para ser ordenado, después de la inicialización de todas las propiedades.
La comprobación de seguridad 1 puede parecer irrelevante ya que, la
inicialización de dos fases evita que se pueda acceder a los valores de propiedad antes de que puedan inicializarse , sin esta comprobación de seguridad 1.
Como en esta muestra
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
ha inicializado, cada propiedad antes de ser utilizada. Entonces el control de seguridad 1 parece irrelevante,
Pero entonces podría haber otro escenario, un poco complejo,
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)
Salida:
Shape Name :Triangle
Sides :3
Hypotenuse :12
Aquí, si hubiéramos llamado al super.init
antes de establecer el hypotenuse
, la super.init
llamada habría llamado al printShapeDescription()
y, dado que se ha anulado, primero recurriría a la implementación de la clase Triangle printShapeDescription()
. La printShapeDescription()
clase Triangle accede a hypotenuse
una propiedad no opcional que aún no se ha inicializado. Y esto no está permitido ya que la inicialización en dos fases evita que se acceda a los valores de propiedad antes de que se inicialicen
Por lo tanto, asegúrese de que la inicialización de dos fases se realice según lo definido, debe haber un orden específico de llamada super.init
, y es decir, después de inicializar todas las propiedades introducidas por la self
clase, por lo tanto, necesitamos un control de seguridad 1