覆盖属性观察者

时间:2015-04-07 23:54:12

标签: swift properties override didset

当我覆盖函数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"

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

3 个答案:

答案 0 :(得分:32)

您可以覆盖属性的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")
    }
}

由于无法超越" didSet,剩下的就是覆盖特别为此目的而创建的辅助功能。

答案 1 :(得分:0)

Swift documentation

  

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

答案 2 :(得分:0)

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

摘自官方文档:Overriding

  

覆盖属性

     

您可以覆盖继承的实例或类型   属性,以提供您自己的自定义获取和设置器   属性,或添加属性观察者以启用覆盖   属性,以便在基础属性值更改时进行观察。