Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么我会得到一个“;初始化前使用的变量";在Swift中初始化变量的行出错?_Ios_Swift - Fatal编程技术网

Ios 为什么我会得到一个“;初始化前使用的变量";在Swift中初始化变量的行出错?

Ios 为什么我会得到一个“;初始化前使用的变量";在Swift中初始化变量的行出错?,ios,swift,Ios,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 {

我很难理解为什么我在使用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()
}

(或者使用属性初始化器
让c=0
),但我想了解为什么编译器在第一个示例中出现问题。我是否遗漏了什么或是不必要的限制?

由于两阶段初始化,Swift有这种行为。摘自苹果的Swift手册:

Swift中的类初始化是一个两阶段的过程。首先 阶段,每个存储的属性由类指定一个初始值 这就引入了它。每个存储属性的初始状态 已确定,第二阶段开始,并给出每个类 有机会在发布之前进一步自定义其存储属性 新实例被认为可以使用

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


Objective-C没有这种行为,因为它始终可以为原语提供默认值
0
,为对象提供默认值
nil
,但在Swift中,没有机制提供这种默认值。

第一阶段何时结束?我本以为
self.c=self.runCalculation()
仍处于第一阶段。在为类层次结构中的根类的存储属性提供初始值后,第一阶段结束。因此,在本例中,当您设置
self.c=0
时,它将结束。如果我使用
self.c=self.a*self.b
而不是调用该方法,则没有问题。调用一个改变事物的方法有什么意义?@rankAmateur:一个方法可以在子类中被重写(它假设超类属性被完全初始化)。@MartinR说得不错。在初始化的第一个阶段完成之前,初始化程序不能调用任何实例方法、读取任何实例属性的值或将self作为值引用?