Modules -> OOP -> Inheritance -> Method extending

Method extending


Related code
class Animal:
    def __init__(self, name, age, energy):
        self.name = name
        self.age = age
        self.energy = energy

    def __str__(self):
        return f"{self.name} is {self.age} years old."

    def play(self, hours):
        self.energy -= hours * 10

    def sleep(self, hours):
        self.energy += hours * 10

In addition to name, age and energy, camels have another characteristic attribute, water_reserve, the amount of water stored in its body.

It is a convention to set attributes in __init__, so if we want to inherit from Animal we need to override it:

class Camel(Animal):
    def __init__(self, name, age, energy, water_reserve):
        self.name = name
        self.age = age
        self.energy = energy
        self.water_reserve = water_reserve

But we still have three common lines of code. In such case, instead of repeating the method implementation, we can call the parent's method inside child's method. This is achieved using super() built-in function:

class Camel(Animal):
    def __init__(self, name, age, energy, water_reserve):
        super().__init__(name, age, energy)
        self.water_reserve = water_reserve

super() refers to parent class, Animal. We called __init__ of Animal, passing required arguments, then we set another extra attribute to Camel, water_reserve.

Note that we didn't pass water_reserve to __init__ of the super class, Animal, because __init__ of animal doesn't accept such argument.

When the camel walks in desert for 1 hour, it spends 10 units of energy, plus 5 liters of water.

class Camel(Animal):
    ...
    def walk_in_desert(self, hours):
        self.energy -= hours * 10
        self.water_reserve -= hours * 5

The first line of this method is the exact implementation of play method. In such case we can call it using self and then add the extra functionality.

class Camel(Animal):
    ...
    def walk_in_desert(self, hours):
        self.play(hours)
        self.water_reserve -= hours * 5

No need to use super() to call the parent's method in this case because there is only one method named play, which we can access directly using self. We use super() when the same method name exists in both the parent and child classes, and we specifically want to invoke the parent class's version.