【问题标题】:Strange "'self' captured by a closure before all members were initialized" error在所有成员初始化之前由闭包捕获的奇怪“'self'”错误
【发布时间】:2019-04-30 13:53:47
【问题描述】:

请看下面的代码:

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 出现错误:

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

有人知道这是为什么吗?

【问题讨论】:

标签: swift


【解决方案1】:

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

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

@autoclosure 使b == bExpectedValue 成为闭包,将其捕获为self.bExpectedValue。在初始化完成之前这是不允许的。 (这里的闭包是为了允许短路。如果 lhs 为假,则不计算 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)
}

【讨论】:

【解决方案2】:

您需要使用另一个变量创建一个新的初始化程序,或者在任何具有此属性的表达式之前调用 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)
}

【讨论】:

  • 酷,非常快的回答,谢谢!但关键不是如何解决,我想知道为什么会发生这种情况。
  • 后者我做不到,因为我得到Argument labels for initializer 'init(newA:newB:)' do not match those of overridden initializer 'init(a:b:)'
  • 您在方法中有变量,例如属性名称,您应该更改方法的变量。
  • 抱歉,我删除了override
  • 您需要使用另一个变量创建一个新的初始化程序,或者在任何具有此属性的表达式之前调用 super.init(a:, b:)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多