Override property observer
Asked Answered
N

3

28

When I override the function noise, the function gets replaced by the new one. But when I override a property with an observer, the old and new value gets both executed.

In playground:

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)")
    }
}

Output:

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

But when I do the same with an property with an observer:

In playground:

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

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

Output:

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

So how am I supposed to override a property with an observer and how to prevent the old values to be executed as well?

Norean answered 7/4, 2015 at 23:54 Comment(2)
It seems no way to prevent the old property observer to be executed.Bloodless
it's amazing you cannot override didSetShitty
F
46

You can override the set and get part of the property and move your println there. This way Swift won't call the original code -- unless you call 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")
        }
    }
}

That's not pretty, though.

Here's a better -- and simpler -- solution:

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

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

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

Since there is no way to "override" the didSet, what remains is overriding a secondary function especially created for that purpose.

Funke answered 8/4, 2015 at 0:29 Comment(3)
As suggested by @nhgrif, I combined the two solutions into a single answer.Funke
Thanks, this helped a bunch. Strange you can't just override didSet. As I've read, apple fixed some bugs related to didSet not so long ago. I got the feeling they still have many bugs to fix regarding didSet.Norean
I don't think allowing property observers to be overridden is likely to be in the works at any point...Grory
G
4

From the 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.

Goody answered 8/8, 2018 at 9:14 Comment(0)
A
0

Observers in subclasses are only added to the one defined in the superclass.

From official documentation: 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.

Amadavat answered 22/5, 2019 at 13:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.