Kevvv
Kevvv

Reputation: 4023

Confusion between self and super in a subclass

Let's say you have a class named Vehicle:

class Vehicle {
    var name: String
    var size: Int
    
    init(name: String, size: Int) {
        self.name = name
        self.size = size
    }
    
    convenience init(name: String) {
        self.init(name: name, size: 100)
    }
    
    func operate() {
        print("operate")
    }
}

If I have a subclass named Car and create a convenience initializer:

class Car: Vehicle {
    convenience init(size: Int) {
        self.init(name: "Vehicle", size: size)
    }
}

the super class' initializer is made available using self.

But, if I want to override the super class' method, it's made available by using super:

class Car: Vehicle {
    // redacted
    
    override func operate() {
        super.operate()
        print("operate a car")
    }
}

If the subclass wants to use the inherited method, it's made available by using self:

class Car: Vehicle {
    // redacted

    func drive() {
        self.operate()
        print("drive")
    }
}

I understand that class methods are instance methods, meaning self refers to the instance of the class. I'm guessing when the subclass inherits the super class' method, it becomes its own instance method. Why does it not apply to overriding? I'm getting confused between the usage of self and super.

Upvotes: 2

Views: 67

Answers (1)

Sweeper
Sweeper

Reputation: 273540

Why does it not apply to overriding?

Well, in this code:

class Car: Vehicle {
    // redacted
    
    override func operate() {
        super.operate()
        print("operate a car")
    }
}

self.operate would refer to the overridden method that is in Car. In other words, if you called self.operate(), it would create infinite recursion. On the other hand, super.operate refers to:

func operate() {
    print("operate")
}

Think of it like this: when you override a method, you kind of "lose" the version of the method that you inherit, and you can only use super to access the original in the super class.

Also, no one stops you from doing:

class Car: Vehicle {
    func drive() {
        super.operate()
        print("drive")
    }
}

It's just that in this case, super.operate() and this.operate() do exactly the same thing, since operate is not overridden in the subclass.

On the other hand, it is illegal to call super.init in a convenience initialiser. You must delegate to a self.init in a convenience initialiser. And in this case, the super class initialisers are inherited because you don't have any designated initialisers (in general, they aren't inherited!). Read more about initialisers here.

Upvotes: 2

Related Questions