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?

Eendje
  • 8,815
  • 1
  • 29
  • 31

3 Answers3

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.

Jean Le Moignan
  • 22,158
  • 3
  • 31
  • 37
  • As suggested by @nhgrif, I combined the two solutions into a single answer. – Jean Le Moignan Apr 08 '15 at 00:53
  • 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`. – Eendje Apr 08 '15 at 00:58
  • I don't think allowing property observers to be overridden is likely to be in the works at any point... – nhgrif Apr 08 '15 at 01:08
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.

Enrico Cupellini
  • 447
  • 7
  • 14
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.

Community
  • 1
  • 1
Lubbo
  • 1,030
  • 1
  • 10
  • 18