Swift 覆盖属性观察者

Swift 覆盖属性观察者,swift,properties,overriding,didset,Swift,Properties,Overriding,Didset,当我重写函数noise时,该函数将被新函数替换。但是当我用一个观察者重写一个属性时,新旧值都会被执行 在游乐场: class Vehicle { func noise(sound: String) { println("Vehicle sound sounds like \(sound)") } } class Train: Vehicle { override func noise(sound: String) { println("A

当我重写函数
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)")
    }
}
class Foo {
    var something: Int! {
        didSet {
            println("vroom")
        }
    }
}

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

var oldTrain = Train()
bulletTrain.noise("tjoek tjoek") // Prints: "A train does: tjoek tjoek"
var foobar = Bar()
foobar.something = 3 // Prints: "vroom" & "toot toot"
但当我对一个观察者的财产做同样的事情时:

在游乐场:

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)")
    }
}
class Foo {
    var something: Int! {
        didSet {
            println("vroom")
        }
    }
}

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

var oldTrain = Train()
bulletTrain.noise("tjoek tjoek") // Prints: "A train does: tjoek tjoek"
var foobar = Bar()
foobar.something = 3 // Prints: "vroom" & "toot toot"

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

您可以覆盖属性的
获取
部分,并将
println
移动到那里。这样,斯威夫特就不会调用原始代码——除非您调用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")
    }
}
由于无法“覆盖”didSet,剩下的就是覆盖专门为此目的创建的辅助函数。

来自

调用超类初始值设定项后,在子类初始值设定项中设置属性时,将调用超类属性的willSet和didSet观察器。在调用超类初始值设定项之前,在类设置自己的属性时不会调用它们


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

从正式文件:

覆盖属性

您可以重写继承的实例或类型 属性提供您自己的自定义getter和setter 属性,或添加属性观察者以启用覆盖 当基础属性值更改时要观察的属性


似乎无法阻止旧的属性观察器被执行。令人惊讶的是,您无法覆盖@nhgrif建议的
didSet
,我将这两个解决方案组合成了一个答案。谢谢,这帮了大忙。奇怪的是,你不能直接覆盖
didSet
。正如我所读到的,苹果不久前修复了一些与didSet相关的bug。我感觉他们仍然有很多关于didSet的bug需要修复。我认为在任何时候都不可能允许覆盖属性观察器。。。