[Python OOP] 3. Inheritance and Polymorphism

04 Nov 2023 By Code Bricks

3. Inheritance and Polymorphism

In this part of our tutorial, we will explore the concepts of inheritance and polymorphism in more detail. These are fundamental to achieving reusability and flexibility in object-oriented programming.

3.1 Deep Dive into Inheritance

Inheritance allows us to define a class that inherits all the methods and properties from another class.

3.1.1 Overriding Methods

When a method in a subclass has the same name as a method in the superclass, it overrides the latter. This is to modify or extend the behavior of the inherited method.

class Animal:
    def speak(self):
        return "This is a generic animal sound."

class Dog(Animal):
    def speak(self):
        return "Woof!"

animal = Animal()
dog = Dog()
print(animal.speak())  # Output: This is a generic animal sound.
print(dog.speak())     # Output: Woof!

3.1.2 The super() Function

The super() function allows us to call methods from the superclass in our subclass, providing a way to extend the functionality rather than just replace it.

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

class Dog(Animal):
    def __init__(self, name):
        super().__init__("Canine")  # Calls the constructor of the superclass
        self.name = name

dog = Dog("Buddy")
print(dog.species)  # Output: Canine
print(dog.name)     # Output: Buddy

3.1.3 Multiple Inheritance

Python allows a class to inherit from multiple classes, enabling it to combine behaviors and attributes of all the base classes.

class Terrestrial:
    def has_legs(self):
        return True

class Aquatic:
    def can_swim(self):
        return True

class Amphibian(Terrestrial, Aquatic):
    pass

frog = Amphibian()
print(frog.has_legs())  # Output: True
print(frog.can_swim())  # Output: True

3.2 Advanced Polymorphism

Polymorphism refers to the way in which different object classes can be accessed through the same interface.

3.2.1 Operator Overloading

Python allows us to define special methods to change the meaning of operators for our objects.

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    # Overload the + operator
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

p1 = Point(1, 2)
p2 = Point(2, 3)
result = p1 + p2
print(result.x, result.y)  # Output: 3 5

3.2.2 Method Overloading

Unlike some other languages, Python does not support method overloading by default. However, we can achieve a similar effect by using default parameters or variable-length argument lists.

class Math:
    def add(self, *args):
        return sum(args)

math = Math()
print(math.add(2, 3))           # Output: 5
print(math.add(2, 3, 4))        # Output: 9

In this way, add can have different numbers of parameters with the same method name.