1
class Person {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class Boy: Person {
    var gf: String! {
        didSet {
            print("have a girlfriend: \(gf)")
        }
    }
    override init(name: String) {
        super.init(name: name)
        gf = "Lilian"
    }
}

I think the property "gf" has been initialized before calling "super.init", and the value is nil. So below "super.init", resetting the "gf" should call its "didSet". But it didn't. I wanna know the reason.

李茂琦
  • 43
  • 3
  • This should solve your problem https://stackoverflow.com/a/25231068/5327882 and also explain why it's not working. Look at the comments of the answer – ronatory Jun 04 '17 at 14:42
  • 1
    First, the behavior is as outlined in [the _The Swift Programming Language_](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID203), which says, "When you assign a default value to a stored property, or set its initial value within an initializer, the value of that property is set directly, without calling any property observers.". Second, in terms of why, I suspect it's because observers can refer to `self`, and you don't want to do that until after initialization is done. – Rob Jun 04 '17 at 14:57
  • I believe there's just a blanket ban on property observers being called from directly within the context of an initialiser, regardless of before or after `super.init`. The rules are more consistent this way, although I do agree that there shouldn't be anything wrong with calling the property observer *after* `super.init` (simple workaround as shown in the linked Q&A is to [use either `defer`](https://stackoverflow.com/a/33979852/2976878) or [an immediately evaluated closure](https://stackoverflow.com/a/29501998/2976878), both of which evade the initialiser context). – Hamish Jun 04 '17 at 15:16
  • It's worth noting that this behaviour actually conflicts with the documentation for property observers – compare https://bugs.swift.org/browse/SR-1118 – Hamish Jun 04 '17 at 15:23
  • @Rob But because OP is setting it after `super.init` in this case, `self` is fully initialised, and therefore the property has already been initialised to the default value of `nil`. So there shouldn't be anything wrong with calling the observer in this case. – Hamish Jun 04 '17 at 15:25
  • @Hamish - Agreed, but as you point out, the current behavior is more consistent and clear. I think it would be significantly worse to have property observers invoked from `self.init()` if performed after `super.init()` but not before. In my opinion, the current, well-documented behavior is simple, predictable and unambiguous. – Rob Jun 04 '17 at 17:07
  • @ronatory I think there are some differences between the two conditions. The point I wanna emphasizing is that after `super.init` the object should be fully initialized and the observer should be called. – 李茂琦 Jun 06 '17 at 04:20

0 Answers0