来自文档
安全检查1
指定的初始值设定项必须确保由其类引入的所有属性在委托给超类初始值设定项之前都已初始化。
为什么我们需要这样的安全检查?
为了解决这个问题,让我们迅速进行初始化过程。
两阶段初始化
Swift中的类初始化是一个两阶段的过程。在第一阶段,每个存储的属性都由引入它的类分配一个初始值。一旦确定了每个存储属性的初始状态,便开始第二阶段,并且在认为新实例可以使用之前,每个类都有机会自定义其存储属性。
两阶段初始化过程的使用使初始化安全,同时仍然为类层次结构中的每个类提供完全的灵活性。两阶段初始化可防止在初始化属性值之前访问属性值,并防止其他初始化程序意外地将属性值设置为其他值。
因此,为确保按照上述定义完成两步初始化过程,需要进行四项安全检查,其中一项是,
安全检查1
指定的初始值设定项必须确保由其类引入的所有属性在委托给超类初始值设定项之前都已初始化。
现在,两阶段初始化从未讨论过顺序,但是super.init
在所有属性初始化之后,此安全检查将引入有序命令。
安全检查1似乎无关紧要,因为如果没有此安全检查1 ,则
两阶段初始化会阻止在属性值被满足之前访问属性值。
像这个样本一样
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
在使用之前,已经初始化了每个属性。因此,安全检查1似乎无关紧要,
但是然后可能会有另一种情况,有点复杂,
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)
输出:
Shape Name :Triangle
Sides :3
Hypotenuse :12
在这里,如果我们super.init
在设置之前调用过hypotenuse
,则该super.init
调用将调用,printShapeDescription()
并且由于已被覆盖,因此它将首先回退到的Triangle类实现printShapeDescription()
。printShapeDescription()
Triangle类的of访问hypotenuse
一个非可选属性,该属性尚未初始化。这是不允许的,因为两阶段初始化阻止了在初始化属性值之前对其进行访问
因此,请确保两阶段初始化已按定义完成,需要有一个特定的调用顺序super.init
,也就是说,在初始化由self
类引入的所有属性之后,因此我们需要进行安全检查1