Kira Ugai
Kira Ugai

Reputation: 11

Are you required to call the a super class's implementation from each and every subclass's function

e.g. you have a subclass defined which overrides a function f in its superclass. Inside the override, are you required to call the superclass's f function.

Upvotes: 0

Views: 707

Answers (3)

mfaani
mfaani

Reputation: 36287

The default is that you call super, unless you know you're not breaking that function.


I've created a gist. You can copy it to your own playground and play around with it. But the answer is:

I had this exact confusion of yours. You're basically asking what's the difference between extending behavior vs. overriding behavior.

Swift doesn't do a good a job of telling your their difference. What they both share is that both need to mark the function with override, but sometimes you're doing something in addition to the superclass's implementation (extending), and sometimes you're just completely rewriting it (overriding)

Suppose we have the following class:

class Person {

    var age : Int?

    func incrementAge() {
        guard age != nil else {
            age = 1
            return
        }
        age! += 1
    }

    func eat() {
        print("eat popcorn")
    }
}

We can just initialize it and do:

var p1 = Person()
p1.incrementAge() // works fine

Now suppose we did this:

class Boy : Person{

    override func incrementAge() {
        age! += 2
    }
}

var b1 = Boy()
b1.incrementAge()

What do you think is going to happen?!

It will crash. Because in the super class, we're doing a nil check for age, but in our subclass we never call super

To make it work we have to call super.

class GoodBoy : Person{

    override func incrementAge() {
        super.incrementAge()
        age! += 2
    }
}

var b2 = GoodBoy()
b2.incrementAge() // works fine. 

We could get away without calling super directly.

class AlternateGoodBoy : Person{

    override func incrementAge() {
        guard age != nil else {
            age = 1
            return
        }
        age! += 2
    }
}

var b3 = AlternateGoodBoy()
b3.incrementAge() // works fine.

^^ The above works, yet the superclass's implementation is not always known to us. A real example is UIKit. We don't know what happens really when viewDidLoad is called. Hence we must call super.viewDidLoad


That being said sometimes we could just not call super and be totally fine because we know what super does or maybe just don't care and want to completely get rid of it. e.g. :

class Girl : Person{
    override func eat() {
        print("eat hotdog")
    }
}

var g1 = Girl()
g1.eat() // doesn't crash, even though you overrode the behavior. It doesn't crash because the call to super ISN'T critical

Yet the most common case is that you call super, but also add something on top of it.

class Dad : Person {
    var moneyInBank = 0
    override func incrementAge() {
        super.incrementAge()
        addMoneyToRetirementFunds()
    }

    func addMoneyToRetirementFunds() {
        moneyInBank += 2000
    }
}

var d1 = Dad()
d1.incrementAge()
print(d1.moneyInBank) // 2000

Pro tip:

Unlike most overrides where you first call super then the rest, for a tearDown function, it’s best to call super.tearDown() at the end of the function. In general, for any 'removal' functions, you'd want to call super at the end. e.g. viewWillDisAppear/viewDidDisappear

Upvotes: 1

slushy
slushy

Reputation: 12375

The answer is false, you don't need to call the superclass method you are overriding in Swift or in OOP in general. That would be a horrible limitation if you did! There are times when you should in fact not call it and perhaps the most common example is when you create a UIViewController programmatically and have to override loadView() without calling super.loadView().

Upvotes: 1

Sulthan
Sulthan

Reputation: 130102

The answer to this question is not really related to Swift but it's related to all OOP languages.

The simple answer is: No, you are not required to call the superclass implementation.

Whether you should call the superclass implementation or not should be stated in the documentation. When you are not sure, you should generally always call the super implementation.

You have to consider the fact that the superclass does something inside the method and if you don't call the superclass implementation, the subclass doesn't have to work properly.

Not calling the superclass implementation means that you want to prevent the superclass implementation from happening and that usually means your whole inheritance model is flawed.

One notable exception is the situation when the superclass provides some default implementation which you want to replace inside your subclass (e.g. UIViewController.loadView). That's not a very common use case though.

There are also other obvious exceptions, for example getters. When you are overriding a getter to return a custom object, there is usually no need to call super. However, again, even getters can technically initialize some structures in the superclass and it might be needed to call super.

Upvotes: 1

Related Questions