错误的“'自我'在所有成员初始化之前被闭包捕获”错误

时间:2019-04-30 13:53:47

标签: swift

请查看以下代码:

class A {
    let a: String
    let b: String

    init(a: String, b: String) {
        self.a = a
        self.b = b
    }
}

class B: A {
    let c: Bool

    private let aExpectedValue = "a"
    private let bExpectedValue = "b"

    override init(a: String, b: String) {
        c = (a == aExpectedValue && b == bExpectedValue)
        super.init(a: a, b: b)
    }
}

这会导致B.init中的错误:

error

但是,如果我将其更改为c = (a == aExpectedValue)c = (b == bExpectedValue),那么它将正确编译。

有人知道为什么吗?

2 个答案:

答案 0 :(得分:12)

问题出在bExpectedValue中。这是B上的一个实例属性。这与Bool上&&的定义相互影响:

static func && (lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool

@autoclosure使b == bExpectedValue成为一个闭包,并将其捕获为self.bExpectedValue。初始化完成之前是不允许的。 (此处的闭合是为了允许短路。如果lhs为false,则不会评估rhs闭合。)

这很尴尬(请参阅MartinR引用的SR-944进行一些讨论)。

如果bExpectedValuestatic,或者如果它移到类定义之外,那么这将不是问题。以下方法也可以解决此问题:

override init(a: String, b: String) {
    let goodA = a == aExpectedValue
    let goodB = b == bExpectedValue
    c = goodA && goodB
    super.init(a: a, b: b)
}

答案 1 :(得分:0)

您需要使用其他变量创建一个新的初始化程序,或者在具有此属性的任何表达式之前调用super.init(a :, b :)。

呼叫此:

override init(a: String, b: String) {
    super.init(a: a, b: b)
    c = (a == aExpectedValue && b == bExpectedValue)        
}

或将其更改为:

init(newA: String, newB: String) {
    c = (newA == aExpectedValue && newB == bExpectedValue)        
    super.init(a: newA, b: newB)
}