当我无法访问自己时,如何初始化依赖于另一个属性的属性?

时间:2014-06-13 18:38:57

标签: swift

我班上有两个属性。看到这个可怕的例子:

var length
var doubleLength

如何根据doubleLength初始化length

init() {
    self.length = ...
    self.doubleLength = self.length * 2

    super.init()
}

我收到错误消息,在我致电self之前无法访问super.init()。好吧,我需要设置所有变量才能调用super.init()所以我该怎么办?

4 个答案:

答案 0 :(得分:4)

如果self.doubleLength总是应该是两次self.length(在这个例子中)你考虑过只使用一个计算属性吗?

class MyClass: MySuperClass {
    var length: Double
    var doubleLength: Double {
        return self.length * 2
    }
    init(len: Double) {
        self.length = len
        super.init()
    }
}

答案 1 :(得分:1)

您可以暂时延迟doubleLength隐式解包的可选项的初始化,这将允许临时为nil分配值并在以后分配它。

class Something: UICollectionViewLayout {
    var doubleLength: Int! = nil
    var length: Int {
        return 50
    }
    init() {
        super.init()
        doubleLength = length * 2
    }
}

无论如何,在这个特定的情况下,我认为使doubleLength计算属性更好,因为它总是可以从length的值计算出来。你的课就像

class Something: UICollectionViewLayout {
    var doubleLength: Int {
        return length * 2
    }
    var length: Int {
        return 50
    }
}

答案 2 :(得分:0)

感谢您的完整复制,即:

import UIKit

class Something: UICollectionViewLayout {
    var doubleLength: Int

    var length: Int {
        return 50
    }

    init() {
        doubleLength = length * 2
        super.init()
    }
}

通过此我们可以看到您使用吸气剂返还您的财产。我认为这是导致问题的原因。例如,如果你这样做:

import UIKit

class Something: UICollectionViewLayout {
    var doubleLength: Int

    // Simple variable, no code.
    var length = 50

    init() {
        doubleLength = length * 2
        super.init()
    }
}

......然后就可以了。

我相信这是因为Swift编译器试图阻止你做任何可能意味着在初始化之前使用基类的方法,属性或变量的事情。在您的示例中,我知道您在技术上,但请考虑追溯并查看您的初始化程序正在完成的操作有多难。例如,如果您要这样做:

var length: Int {
    // Where "width" is a made-up property of UICollectionViewLayout
    return width * 3
}

...然后您的代码将从您的初始化程序运行并在调用其自己的init之前使用UICollectionViewLayout的属性,因此可能使其无效。

所以我最好的猜测是,这是Swift编译器在超级初始化之前全局禁止在子类初始化器之外调用任何代码。

如果你这样做,你会得到完全相同的错误,例如:

class Something: UICollectionViewLayout {    
    func foo() {
        // Do nothing
    }

    init() {
        foo() // error: 'self' used before super.init call
        super.init()
    }
}

我记得这个被解释的地方是"中级斯威夫特"来自WWDC 2014的视频,来自幻灯片191,大约20分钟,但我也猜测它在书中的某个地方......

答案 3 :(得分:-6)

依赖他人的财产是不好的做法。就像设计数据库时一样,避免计算字段,在设计类时,也可以避免计算字段。您应该使用返回长度* 2的getDoubleLength方法,而不是拥有doubleLength属性。