Can anyone explain the behaviour when subclassing properties? I am sure there is a good explanation for why 'override' does not actually override the property.

Why does Swift allow the surname property to be overridden but apparently still uses the super class's property and associated functions? They are not overridden.

It would seem that I would have to define some function that gets called in the didSet() method and override that to ensure the subclass does not inherit the super class's function as with the telephone property.

Is there any way to override a property's didSet() method? Creating some function that gets called seems to add an unnecessary extra complexity?

What is the correct way of achieving this?

import Cocoa

class BaseClass {
    var _name: String?
    var name: String? {
        get {
            return _name
        }
        set {
            _name = newValue
            print("BaseClass \(name)")
        }
    }

    var surname: String? {
        didSet {
            print("BaseClass \(surname)")
        }
    }

    var telephone: String? {
        didSet {
            telephoneSet()
        }
    }

    func telephoneSet(){
        print("BaseClass \(telephone)")
    }
}

class SubClass: BaseClass {
    override var name: String? {
        get {
            return _name
        }
        set {
            _name = newValue
            print("SubClass \(name)")
        }
    }
    override var surname: String? {
        didSet {
            print("SubClass \(surname)")
        }
    }

    override func telephoneSet(){
        print("SubClass \(telephone)")
    }
}


let object = SubClass()

object.name = "Jenny"
object.surname = "Jones"
object.telephone = "10810"

Generates the following output:

SubClass Optional("Jenny")
BaseClass Optional("Jones")
SubClass Optional("Jones")
SubClass Optional("10810")

1 Answers

0
Rob On

Let’s simplify your example and get rid of the unrelated stuff:

class BaseClass {
    var surname: String? {
        didSet { print("BaseClass \(surname)") }
    }
}

class SubClass: BaseClass {
    override var surname: String? {
        didSet { print("SubClass \(surname)") }
    }
}

Then:

let object = SubClass()
object.surname = "Jones"

Will produce:

BaseClass Optional("Jones")
SubClass Optional("Jones")

Note, the above is not overriding the stored property, surname with another stored property. It simply is the stored property of the base class and all you’re doing is letting the subclass add an observer to this property. I refer you to The Swift Programming Language: Inheritance: Overriding, which says:

Overriding Property Observers

You can use property overriding to add property observers to an inherited property. This enables you to be notified when the value of an inherited property changes, regardless of how that property was originally implemented.

In your example of name, you are overriding the computed property with the subclasses’ own computed property. Likewise, in your example of telephoneSet, you are also overriding the method with the subclasses’ own method. But with surname, you’re not overriding the base classes’ property, but merely letting the subclass add an observer to the base classes’ stored property.