请查看以下代码:
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)
,那么它将正确编译。
有人知道为什么吗?
答案 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进行一些讨论)。
如果bExpectedValue
是static
,或者如果它移到类定义之外,那么这将不是问题。以下方法也可以解决此问题:
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)
}