【问题标题】:Swift error using initialized properties in expressions before super.init在 super.init 之前在表达式中使用初始化属性的 Swift 错误
【发布时间】:2015-02-02 19:40:41
【问题描述】:

这并不重要,也有一些变通方法,但令人困惑。

请参阅下面的最小示例。我指的是一个初始化的属性,但在调用 super.init() 之前。为什么下面指示的语句有编译错误?使用表达式右手和左手的属性有什么特别之处吗?

我浏览了 Swift 语言指南,但找不到任何相关内容。快速编译器在这里搞砸了,还是我缺少一些关于属性、自我和初始化的东西?或者在调用 super.init 之前 所有 对“myProperty”的引用是否有误?

(请注意,如果属性是常量(使用 'let')或属性是否为其他类型(如 Int)并不重要——同样的事情也会发生。)

class MyClass : NSObject {
    var myProperty: Bool

    override init() {
        myProperty = true

        if myProperty { /* this is ok */ }
        if myProperty || true { /* this is ok */ }
        if true || myProperty  { /* this is NOT ok! ('self used before super.init') - WHY? */ }

        super.init()

        if true || myProperty  { /* now this is ok */ }
    }
}

【问题讨论】:

    标签: swift properties initialization


    【解决方案1】:

    这是|| 被声明为的副作用

    func ||<T : BooleanType>(lhs: T, rhs: @autoclosure () -> Bool) -> Bool
    

    所以编译器处理

    true || myProperty
    

    作为

    true || { self.myProperty }()
    

    原因是|| 运算符的“短路” 行为:如果第一个 操作数为真,则不能计算第二个操作数。

    (旁注:我假设这在后面的阶段被简化了 编译/优化过程 这样最终的代码实际上不会创建和调用闭包。)

    在闭包内访问self 会导致错误消息。你会 得到同样的错误

    override init() {
        myProperty = true
        let a = { self }() // ERROR: self used before super.init
        super.init()
        let b = { self }() // OK after super.init
    }
    

    【讨论】:

    • 哇,谢谢,这解释了不对称性以及 RHS 与其他非表达式用法不同的原因,即引入“自我”参考。令人惊讶的是,这种“干净和简单”的语言有多么复杂!很好的答案。
    【解决方案2】:

    我认为是intended behavior 和两阶段初始化的一部分。

    这是以下规则的结果:

    • 所有属性必须在调用super.init之前初始化,即在声明的同一行或在super.init之前的init中
    • 初始化器可能不会调用任何实例方法,读取任何实例属性的值,或者将 self 作为值引用直到第一个阶段之后初始化完成

    【讨论】:

    • 按照这个逻辑,前两个“if”语句也应该是错误的,因为它们引用了阶段 1 完成之前实例属性的值。所以这个问题仍然是开放的,只是反过来:这是一个 Swift 错误,前 2 个 'if' 被接受了吗?
    • 是的,在这种情况下,我希望您的其他两个语句也会失败。
    猜你喜欢
    • 2020-07-06
    • 1970-01-01
    • 2014-07-24
    • 2021-12-22
    相关资源
    最近更新 更多