一尘不染

为什么在Swift中初始化变量的行上出现“初始化前使用变量”错误?

swift

我正在努力理解为什么我在使用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’” 这一行上收到编译器错误。

起初我以为这是因为编译器无法验证该runCalculation()方法是否无法访问self.c,但是后来我尝试将init方法混入一点:

init () {
    self.a = 3
    self.c = self.runCalculation()
    self.b = 4
}

这次的错误是“在初始化之前使用了变量’self.b’”(在同一self.runCalculation()行上)。这表明编译器
能够检查其性能的方法访问,所以据我可以看到应该有最初的情况下,没有问题的。

当然,这是一个简单的示例,我可以轻松地进行重构以避免调用计算方法,但是在实际项目中,可能会有多个计算,每个计算都可能涉及到很多。我希望能够分离出保持可读性的逻辑。

幸运的是,有一个简单的解决方法:

init () {
    self.a = 3
    self.b = 4

    self.c = 0
    self.c = self.runCalculation()
}

(或使用属性初始化程序let c = 0),但我想了解为什么编译器在第一个示例中有问题。我是否缺少某些东西,还是不必要的限制?


阅读 195

收藏
2020-07-07

共1个答案

一尘不染

由于两阶段初始化,Swift具有此行为。从Apple的Swift书中:

Swift中的类初始化是一个分为两个阶段的过程。在第一阶段,每个存储的属性都由引入它的类分配一个初始值。一旦确定了每个存储属性的初始状态,便开始第二阶段,并且在考虑将新实例准备使用之前,每个类都有机会自定义其存储属性。

在第一阶段结束之前,类需要某种默认值。定制值是第二阶段的一部分。

Objective-C没有这种行为,因为它总是可以0为基元和nil对象提供默认值,但是在Swift中,没有机制可以提供此类默认值。

2020-07-07