Python - Inheritance

What is Inheritance in Python?

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows one class to inherit the properties and methods of another class. This enables code reusability and modularity, as you can create new classes based on existing ones without having to write the same code again. In Python, inheritance is implemented using the class keyword followed by the name of the parent class in parentheses.

Python - Inheritance

Creating a Parent Class

Let's start by creating a simple parent class called Animal:

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("Subclass must implement this method")

In this example, we define an Animal class with an __init__ method that initializes the name attribute and a speak method that raises a NotImplementedError. This error will be raised if the subclass does not provide its own implementation of the speak method.

Creating a Child Class

Now, let's create a child class called Dog that inherits from the Animal class:

class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

The Dog class inherits all the attributes and methods of the Animal class, but it provides its own implementation of the speak method. When we create an instance of the Dog class and call its speak method, it will return "[dog's name] says Woof!" instead of raising an error.

my_dog = Dog("Buddy")
print(my_dog.speak())  # Output: Buddy says Woof!

Types of Inheritance

There are three types of inheritance in Python: single inheritance, multiple inheritance, multilevel inheritance, and hierarchical inheritance. We'll explore each type in detail.

Python - Single Inheritance

Single inheritance is the most common form of inheritance, where a class inherits from only one parent class. As we've seen above, the Dog class inherits from the Animal class, which is an example of single inheritance.

Python - Multiple Inheritance

Multiple inheritance is when a class inherits from more than one parent class. However, Python does not support multiple inheritance directly through the class definition syntax. Instead, it uses a technique called "mixins" or "interfaces" to achieve multiple inheritance.

Method Resolution Order (MRO)

Python uses the C3 linearization algorithm to determine the order in which base classes are searched when looking for a method. The MRO ensures that each class appears at most once in the method resolution order, and it maintains the order of the base classes as they were specified in the class definition.

Python - Multilevel Inheritance

Multilevel inheritance occurs when a class inherits from a subclass, forming a hierarchy of classes. Here's an example:

class Mammal(Animal):
    pass

class Cat(Mammal):
    def speak(self):
        return f"{self.name} says Meow!"

In this case, the Cat class inherits from the Mammal class, which in turn inherits from the Animal class. This forms a multilevel inheritance hierarchy.

Python - Hierarchical Inheritance

Hierarchical inheritance involves multiple subclasses inheriting from a single superclass. For example:

class Reptile(Animal):
    pass

class Snake(Reptile):
    def speak(self):
        return f"{self.name} says Hiss!"

class Lizard(Reptile):
    def speak(self):
        return f"{self.name} says Crawl!"

In this case, both Snake and Lizard classes inherit from the Reptile class, which in turn inherits from the Animal class. This forms a hierarchical inheritance structure.

Python - Hybrid Inheritance

Hybrid inheritance combines features of multiple inheritance and other types of inheritance. It's not directly supported in Python, but can be achieved using mixins or by combining different types of inheritance.

The super() function

The super() function is used to call methods from the parent class within the subclass. It's particularly useful when you want to extend or override a method from the parent class while still retaining some of its functionality. Here's an example:

class Bird(Animal):
    def __init__(self, name, wingspan):
        super().__init__(name)
        self.wingspan = wingspan

    def speak(self):
        return f"{self.name} says Chirp!"

In this case, the Bird class inherits from the Animal class and uses the super() function to call the __init__ method of the parent class. This ensures that the name attribute is properly initialized. Additionally, the Bird class provides its own implementation of the speak method.

my_bird = Bird("Tweety", 10)
print(my_bird.speak())  # Output: Tweety says Chirp!

By using inheritance, you can create more specialized classes that inherit and extend the functionality of their parent classes, promoting code reusability and organization. Remember that inheritance is just one aspect of OOP, and there are other concepts like polymorphism, encapsulation, and abstraction that also play a crucial role in designing robust and maintainable software systems.

Credits: Image by storyset