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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27038889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:42:51  来源:igfitidea点击:

Why do I get a "Variable used before being initialized" error on the line that I initialise the variable in Swift?

iosswift

提问by rankAmateur

I'm struggling to understand why I'm getting this compiler error in an iOS project using Swift. If I create the following class:

我正在努力理解为什么我在使用 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
    }
}

I get a compiler error on the line self.c = self.runCalculation()saying "Variable 'self.c' used before being initialized".

我在行上收到一个编译器错误,self.c = self.runCalculation()提示“在初始化之前使用了变量‘self.c’”。

At first I thought this was because the compiler could not verify that the runCalculation()method did not access self.c, but then I tried mixing the init method up a bit:

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

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

and this time the error is "Variable 'self.b' used before being initialized" (on the same self.runCalculation()line). This indicates that the compiler iscapable of checking which properties the method accesses, and so as far as I can see should have no issue with the initial case.

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

Of course this is a trivial example and I could easily refactor to avoid calling the calculation method, but in a real project there could be several calculations each of which could be quite involved. I'd like to be able to separate out the logic to keep things readable.

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

Fortunately there's a simple workaround:

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

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

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

(or using a property initialiser let c = 0) but I'd like to understand why the compiler has a problem with the first example. Am I missing something or is it an unnecessary restriction?

(或使用属性初始化程序let c = 0)但我想了解为什么编译器对第一个示例有问题。我是不是遗漏了什么,还是不必要的限制?

回答by Kirsteins

Swift has this behaviour because of two phase initialisation. From Apple's Swift book:

由于两阶段初始化,Swift 具有这种行为。来自 Apple 的 Swift 书:

Class initialization in Swift is a two-phase process. In the first phase, each stored property is assigned an initial value by the class that introduced it. Once the initial state for every stored property has been determined, the second phase begins, and each class is given the opportunity to customize its stored properties further before the new instance is considered ready for use.

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

Classes need some kind of default value before the first phase ends. Customising values is part of the second phase.

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

Objective-C didn't have this behaviour because it could always give 0as default for primitives and nilfor objects, but in Swift there is no mechanism to give such a default value.

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