覆盖 属性 观察者

Override property observer

当我覆盖函数 noise 时,该函数被新函数替换。但是当我用观察者覆盖 属性 时,旧值和新值都会被执行。

操场上:

class Vehicle {
    func noise(sound: String) {
        println("Vehicle sound sounds like \(sound)")
    }
}

class Train: Vehicle {
    override func noise(sound: String) {
        println("A train does: \(sound)")
    }
}

输出:

var oldTrain = Train()
bulletTrain.noise("tjoek tjoek") // Prints: "A train does: tjoek tjoek"

但是当我对 属性 和观察者做同样的事情时:

操场上:

class Foo {
    var something: Int! {
        didSet {
            println("vroom")
        }
    }
}

class Bar: Foo {
    override var something: Int! {
        didSet {
            println("toot toot")
        }
    }
}

输出:

var foobar = Bar()
foobar.something = 3 // Prints: "vroom" & "toot toot"

那么我应该如何用观察者覆盖 属性 以及如何防止旧值也被执行?

您可以覆盖 属性 的 setget 部分并将您的 println 移到那里。这样 Swift 就不会调用原始代码——除非你调用 super.

class Foo {
    private var _something: Int!

    var something: Int! {
        get {
            return _something
        }
        set {
            _something = newValue
            println("vroom")
        }
    }
}

class Bar: Foo {
    override var something: Int! {
        get {
            return _something
        }
        set {
            _something = newValue
            println("toot toot")
        }
    }
}

不过,这并不漂亮。

这是一个更好、更简单的解决方案:

class Foo {
    var something: Int! {
        didSet {
            somethingWasSet()
        }
    }

    func somethingWasSet() {
        println("vroom")
    }
}

class Bar: Foo {
    override func somethingWasSet() {
        println("toot toot")
    }
}

由于无法 "override" didSet,剩下的就是覆盖专门为此目的创建的辅助函数。

来自Swift documentation

The willSet and didSet observers of superclass properties are called when a property is set in a subclass initializer, after the superclass initializer has been called. They are not called while a class is setting its own properties, before the superclass initializer has been called.

子类中的观察者仅添加到超类中定义的观察者。

来自官方文档:Overriding

Overriding Properties

You can override an inherited instance or type property to provide your own custom getter and setter for that property, or to add property observers to enable the overriding property to observe when the underlying property value changes.