Inheritance is a fundamental concept in Object-Oriented Programming (OOP) that allows a child class to inherit attributes and methods from a parent class. This promotes code reuse, reduces redundancy, and improves maintainability.
Why Use Inheritance?
Code Reusability – Avoid duplicate code by reusing existing classes
Extensibility – Modify or extend behavior without changing the original class
Maintainability – Easier to manage and update code
1. Understanding Inheritance
1.1 Defining a Parent and Child Class
A child class inherits from a parent class by passing the parent class as a parameter.
class Animal: # Parent class
def __init__(self, name):
self.name = name
def speak(self):
print("Animal makes a sound")
class Dog(Animal): # Child class
def __init__(self, name, breed):
super().__init__(name) # Call parent constructor
self.breed = breed
def speak(self): # Overriding parent method
print("Bark!")
dog = Dog("Buddy", "Golden Retriever")
dog.speak() # Output: Bark!
Here, Dog inherits from Animal, and the speak()
method is overridden.
2. Types of Inheritance in Python
2.1 Single Inheritance
A child class inherits from a single parent class.
class Vehicle:
def __init__(self, brand):
self.brand = brand
def show(self):
print(f"Brand: {self.brand}")
class Car(Vehicle): # Inheriting from Vehicle
def __init__(self, brand, model):
super().__init__(brand)
self.model = model
def show(self):
print(f"Brand: {self.brand}, Model: {self.model}")
car = Car("Toyota", "Corolla")
car.show()
Output:
Brand: Toyota, Model: Corolla
2.2 Multiple Inheritance
A child class can inherit from multiple parent classes.
class Engine:
def start(self):
print("Engine started")
class Wheels:
def rotate(self):
print("Wheels rotating")
class Car(Engine, Wheels): # Multiple inheritance
def drive(self):
print("Car is moving")
car = Car()
car.start() # From Engine class
car.rotate() # From Wheels class
Output:
Engine started
Wheels rotating
Avoid multiple inheritance if it leads to complexity or ambiguity.
2.3 Multilevel Inheritance
A class inherits from another class, which itself inherits from another class.
class Grandparent:
def family_name(self):
print("Family: Smith")
class Parent(Grandparent):
def parent_name(self):
print("Parent: John")
class Child(Parent): # Child inherits from Parent
def child_name(self):
print("Child: Alice")
child = Child()
child.family_name() # Inherited from Grandparent
child.parent_name() # Inherited from Parent
child.child_name() # Defined in Child
Output:
Family: Smith
Parent: John
Child: Alice
2.4 Hierarchical Inheritance
Multiple child classes inherit from the same parent class.
class Animal:
def sound(self):
print("Some sound")
class Dog(Animal):
def sound(self):
print("Bark!")
class Cat(Animal):
def sound(self):
print("Meow!")
dog = Dog()
cat = Cat()
dog.sound() # Output: Bark!
cat.sound() # Output: Meow!
2.5 Hybrid Inheritance
A combination of multiple inheritance and multilevel inheritance.
class A:
def method_A(self):
print("Method A")
class B(A):
def method_B(self):
print("Method B")
class C(A):
def method_C(self):
print("Method C")
class D(B, C): # Hybrid Inheritance
def method_D(self):
print("Method D")
obj = D()
obj.method_A() # From class A
obj.method_B() # From class B
obj.method_C() # From class C
obj.method_D() # From class D
Be cautious with Hybrid Inheritance as it can create a complex hierarchy.
3. Method Overriding in Inheritance
A child class can redefine a method from its parent class to change its behavior.
class Parent:
def show(self):
print("Parent class method")
class Child(Parent):
def show(self): # Overriding the parent method
print("Child class method")
child = Child()
child.show() # Output: Child class method
4. The super()
Function
The super()
function allows a child class to call a parent class method.
class Person:
def __init__(self, name):
self.name = name
def display(self):
print(f"Name: {self.name}")
class Employee(Person):
def __init__(self, name, salary):
super().__init__(name) # Call parent constructor
self.salary = salary
def display(self):
super().display() # Call parent method
print(f"Salary: {self.salary}")
emp = Employee("Alice", 5000)
emp.display()
Output:
Name: Alice
Salary: 5000
5. The Method Resolution Order (MRO)
When multiple classes are inherited, Python follows the C3 linearization (Depth-First Left-to-Right Order) to resolve method calls.
class A:
def show(self):
print("Class A")
class B(A):
def show(self):
print("Class B")
class C(A):
def show(self):
print("Class C")
class D(B, C): # Multiple Inheritance
pass
obj = D()
obj.show() # Output: Class B (because B is first in the order)
Use ClassName.__mro__
or help(ClassName)
to check the Method Resolution Order (MRO).
print(D.__mro__)
6. Real-World Example: Employee Management System
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def display(self):
print(f"Name: {self.name}, Salary: {self.salary}")
class Manager(Employee):
def __init__(self, name, salary, department):
super().__init__(name, salary)
self.department = department
def display(self):
super().display()
print(f"Department: {self.department}")
mgr = Manager("John", 8000, "HR")
mgr.display()
Output:
Name: John, Salary: 8000
Department: HR