Please take a look at the following code:
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)
}
}
This causes an error in B.init:

However, if I change it either to c = (a == aExpectedValue) or c = (b == bExpectedValue) then it compiles correctly.
Does anybody know why is that?
The problem is in bExpectedValue. That's an instance property on B. That interacts with the definition of && on Bool:
static func && (lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool
The @autoclosure makes the b == bExpectedValue into a closure, capturing it as self.bExpectedValue. That's not allowed before initialization is complete. (The closure here is to allow short-circuiting. The rhs closure is not evaluated if lhs is false.)
This is pretty awkward (see SR-944 that MartinR references for a little discussion about it).
If bExpectedValue were static, or if it were moved outside the class definition, then this wouldn't be an issue. The following approach will also fix it:
override init(a: String, b: String) {
let goodA = a == aExpectedValue
let goodB = b == bExpectedValue
c = goodA && goodB
super.init(a: a, b: b)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With