我正在努力理解为什么我在使用Swift的iOS项目中遇到此编译器错误。如果我创建以下类:
class InitTest { let a: Int let b: Int let c: Int init () { self.a = 3 self.b = 4 self.c = self.runCalculation() } func runCalculation () -> Int { return self.a * self.b } }
我在self.c = self.runCalculation()“初始化前使用了变量’self.c’” 这一行上收到编译器错误。
self.c = self.runCalculation()
起初我以为这是因为编译器无法验证该runCalculation()方法是否无法访问self.c,但是后来我尝试将init方法混入一点:
runCalculation()
self.c
init () { self.a = 3 self.c = self.runCalculation() self.b = 4 }
这次的错误是“在初始化之前使用了变量’self.b’”(在同一self.runCalculation()行上)。这表明编译器 是 能够检查其性能的方法访问,所以据我可以看到应该有最初的情况下,没有问题的。
self.runCalculation()
当然,这是一个简单的示例,我可以轻松地进行重构以避免调用计算方法,但是在实际项目中,可能会有多个计算,每个计算都可能涉及到很多。我希望能够分离出保持可读性的逻辑。
幸运的是,有一个简单的解决方法:
init () { self.a = 3 self.b = 4 self.c = 0 self.c = self.runCalculation() }
(或使用属性初始化程序let c = 0),但我想了解为什么编译器在第一个示例中有问题。我是否缺少某些东西,还是不必要的限制?
let c = 0
由于两阶段初始化,Swift具有此行为。从Apple的Swift书中:
Swift中的类初始化是一个分为两个阶段的过程。在第一阶段,每个存储的属性都由引入它的类分配一个初始值。一旦确定了每个存储属性的初始状态,便开始第二阶段,并且在考虑将新实例准备使用之前,每个类都有机会自定义其存储属性。
在第一阶段结束之前,类需要某种默认值。定制值是第二阶段的一部分。
Objective-C没有这种行为,因为它总是可以0为基元和nil对象提供默认值,但是在Swift中,没有机制可以提供此类默认值。
0
nil