This is an archived version of the course and is no longer updated. Please find the latest version of the course on the main webpage.

Implementing Inheritance

Let us implement some of our classes in our example. We will create a Character class, and a Enemy subclass that inherits from Character. For simplicity, we will only implement a subset of the attributes and methods.

Inheritance example

class Character:
    def __init__(self, name, health=50, strength=30, defence=20):
        self.name = name
        self.health = health
        self.strength = strength
        self.defence = defence

    def attack(self, character):
        character.health = character.health - self.strength
        print(f"Bam! {self.name} attacked {character.name}.", 
             f"{character.name}'s health is now {character.health}")

    def defend(self, character):
        self.health = self.health - character.strength * 0.25
        print(f"{self.name} defended against {character.name}.",
             f"{self.name}'s health is now {self.health}")

    def __str__(self):
        return f"{self.name} is a Character (health: {self.health},"\
               f"strength: {self.strength}, defence: {self.defence})" 

class Enemy(Character):
    def __init__(self, name, health=50, strength=30, defence=20, evilness=50):
        self.evilness = 50

        # call the constructor of the superclass
        super().__init__(name, health, strength, defence)
        
    def evil_laugh(self):
        print("Hehehehehe!")    

    def __str__(self):
        return f"{self.name} is an Enemy (health: {self.health},"\
               f"strength: {self.strength}, defence: {self.defence},"\
               f"evilness: {self.evilness})" 


boy = Character("Boy", 100, 20, 10)
evilman = Enemy("Voldemort", 30, 50, 40, 100)
print(boy)
print(evilman)
evilman.attack(boy)
boy.defend(evilman)
boy.evil_laugh()  # You should get an error here.

super() refers to the superclass - in this case it is Character.

As you may have observed, Enemy has fewer lines of code than Character, despite being more powerful. We did not have to explictly define the attributes name, health, strength and defence in Enemy. Enemy inherits all these from Character, thus a simple call to the constructor of the superclass is sufficient.

evilman was also able to attack the poor boy without having to explicitly define the attack() method.

boy cannot however express an evil_laugh() because it neither implemented that method nor inherited that method from any superclass.

Method overriding

Let us now try to implement the Monster class, and also let it have its own evil laughter rather than following the default laughter of Enemy! 👾

class Monster(Enemy):
    def __init__(self, name, health=50, strength=30, defence=20, evilness=50, smelliness=100):
        self.smelliness = smelliness
        super().__init__(name, health, strength, defence, evilness)

    def evil_laugh(self):
        print("WAHAHAHAHAHAHAHAHAHA!!! HA!!")

monster = Monster("Bigfoot", 100, 70, 40, 50, 1000)
monster.evil_laugh()

So, the monster now has its own customised evil laugh. WAHAHAHAHAHAHAHAHAHA!!! HA!!

This is called method overriding.