来自docs
安全检查 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
如果我们在设置hypotenuse 之前调用了super.init,那么super.init 调用将调用printShapeDescription(),并且由于它已被覆盖,它将首先回退到printShapeDescription() 的三角形类实现. Triangle 类的printShapeDescription() 访问hypotenuse 一个尚未初始化的非可选属性。这是不允许的,因为两阶段初始化会阻止属性值在初始化之前被访问
所以要确保两阶段初始化按照定义完成,需要有一个特定的调用super.init的顺序,也就是在初始化所有self类引入的属性之后,所以我们需要一个安全检查 1