6.3. Extending Types#

In addition to creating our own classes, we can also extend the functionality of existing classes. This is done through Inheritance.

6.3.1. Inheritance#

Inheritance is the process by which one class takes on the attributes and methods of another. The new class is called derived (or child) class and the one from which it is derived is called the base (or parent) class. The derived class inherits all the features from the base class and can have additional features of its own.

It’s important to note that child classes override or extend the functionality (e.g., attributes and behaviors) of parent classes. In other words, child classes inherit all of the parent’s attributes and behaviors but can also specify different behavior to follow. The most basic type of class is an object, which generally all other classes inherit as their parent.

https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/images/Python_ShapeAndSubclasses.png

Fig. 6.8 Inheritance is a powerful feature in object oriented programming. It refers to defining a new class with little or no modification to an existing class. The new class is called derived (or child) class and the one from which it is derived is called the base (or parent) class. In the figure above, Circle and Rectangle are derived classes of Shape class. Similarly, Square is a derived class of Rectangle class.#

Inheritance is a powerful feature in object oriented programming. It refers to defining a new class with little or no modification to an existing class.

class ParentClass:
    # class definition
    x = 1

class ChildClass(ParentClass):
    # class definition
    pass

# create an object of the ChildClass
obj = ChildClass()
obj.x
1

In the above example, ChildClass is derived from ParentClass. The derived class ChildClass inherits all the features from the base class ParentClass.

In this example, we have a class Rectangle and a class Square that inherits from Rectangle.

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * (self.length + self.width)

class Square(Rectangle):

    def __init__(self, side):
        super().__init__(side, side)

6.3.2. Overriding Methods#

Inheritance allows us to inherit attributes and methods from a parent class. This is useful because we can create a child class that inherits from a parent class and then add new attributes and methods to the child class.

Sometimes, we want to change the behavior of a method in the child class. This is called overriding. We can override a method in the child class by defining a method with the same name in the child class.

class ParentClass:
    def method(self):
        print("This is a method from the parent class")

class ChildClass(ParentClass):
    def method(self):
        print("This is a method from the child class")

child = ChildClass()
child.method()
This is a method from the child class

6.3.3. super()#

When you add the __init__() function, the child class will no longer inherit the parent’s __init__() function.

The super() function is used to give access to methods and properties of a parent or sibling class. The super() function returns an object that represents the parent class.

class ParentClass:
    def __init__(self, name, age):
        self.name = name
        self.age = age

class ChildClass(ParentClass):
    def __init__(self, name, age, year):
        super().__init__(name, age)
        self.year = year

child = ChildClass("John", 30, 1990)

child.age
30

super() function that will make the child class inherit all the methods and properties from its parent. By using the super() function, you do not have to use the name of the parent element, it will automatically inherit the methods and properties from its parent.

6.3.4. Types of Inheritance#

There are different types of inheritance, such as:

  • Single Inheritance: When a class inherits from only one class. It is the simplest type of inheritance.

  • Multiple Inheritance: When a class inherits from more than one class. It is not supported in Python.

  • Multilevel Inheritance: When a class inherits from a derived class.

  • Hierarchical Inheritance: When more than one class inherits from a class.

  • Hybrid Inheritance: When a class is derived from two classes and these two classes are derived from one class.



# Examples of types of inheritance

class A:
    def __init__(self):
        print("A")

class B(A): # single inheritance
    def __init__(self):
        super().__init__()
        print("B")

class C(B): # multi-level inheritance
    def __init__(self):
        super().__init__()
        print("C")
    
class D(A): # hierarchical inheritance
    def __init__(self):
        super().__init__()
        print("D")

class E(D, C):  # multiple inheritance
    def __init__(self):
        super().__init__()
        print("E")

obj = E()
A
B
C
D
E

6.3.5. Polymorphism#

Polymorphism is the ability to use a common interface for different data types or classes. It allows us to define a single interface and have multiple implementations.

Polymorphism is an important feature of class definition in Python that is utilized when you have commonly named methods across classes or subclasses. This allows functions to use objects of any of these polymorphic classes without needing to be aware of distinctions across the classes.

class Dog:
    def speak(self):
        print("Woof!")

class Cat:
    def speak(self):
        print("Meow!")

pet = Dog()
pet.speak()

pet = Cat()
pet.speak()
Woof!
Meow!

A simple example of polymorphism is the len() function. It can be used with different data types, such as strings, lists, and tuples.

print(len("Hello")) # 5
print(len([1, 2, 3])) # 3
print(len((1, 2, 3))) # 3

Another example is the + operator. It can be used to add numbers or concatenate strings.

print(1 + 2) # 3
print("Hello" + " " + "World") # Hello World