Back to blog
← View series: python tutorials

~/blog

OOP - Inheritance & Polymorphism

Apr 1, 20266 min readBy Mohammed Vasim
PythonProgrammingTutorialBeginner

Introduction

In this tutorial, you'll learn about two fundamental OOP concepts: inheritance and polymorphism. Inheritance allows you to create new classes based on existing ones, while polymorphism allows objects of different classes to be treated uniformly.

What You'll Learn

  • What is inheritance
  • Creating subclasses
  • The super() function
  • Method overriding
  • Multiple inheritance
  • What is polymorphism
  • Duck typing

What is Inheritance?

Inheritance is a way to create a new class from an existing class. The new class (child/subclass) inherits attributes and methods from the existing class (parent/superclass).

Why Use Inheritance?

BenefitDescription
Code ReuseDon't write same code twice
OrganizationClear relationship between classes
ExtensibilityAdd features without modifying parent
MaintainabilityChanges in one place affect all children

Basic Inheritance

python
# Parent class (also called base class)
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return "Some sound"
    
    def eat(self):
        return f"{self.name} is eating"

# Child class (inherits from Animal)
class Dog(Animal):
    def speak(self):
        return "Woof!"

# Create instances
animal = Animal("Generic Animal")
dog = Dog("Buddy")

print(animal.speak())  # Some sound
print(dog.speak())     # Woof!
print(dog.eat())       # Buddy is eating

The super() Function

The super() function allows you to call methods from the parent class:

python
class Animal:
    def __init__(self, name):
        self.name = name
    
    def __str__(self):
        return f"Animal: {self.name}"

class Dog(Animal):
    def __init__(self, name, breed):
        # Call parent's __init__
        super().__init__(name)
        self.breed = breed
    
    def __str__(self):
        return f"Dog: {self.name} ({self.breed})"
    
    def speak(self):
        return "Woof!"

dog = Dog("Buddy", "Golden Retriever")
print(dog)           # Dog: Buddy (Golden Retriever)
print(dog.speak())   # Woof!

Method Overriding

Child classes can override (replace) methods from the parent class:

python
class Shape:
    def area(self):
        return 0
    
    def perimeter(self):
        return 0

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    # Override area method
    def area(self):
        return self.width * self.height
    
    # Override perimeter method
    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14159 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14159 * self.radius

# Test
rect = Rectangle(5, 3)
circle = Circle(2)

print(f"Rectangle area: {rect.area()}")      # 15
print(f"Rectangle perimeter: {rect.perimeter()}")  # 16
print(f"Circle area: {circle.area()}")        # 12.56636
print(f"Circle perimeter: {circle.perimeter()}")  # 12.56636

Multiple Inheritance

A class can inherit from multiple parent classes:

python
class Flyable:
    def fly(self):
        return "Flying!"

class Swimmable:
    def swim(self):
        return "Swimming!"

# Duck inherits from both
class Duck(Flyable, Swimmable):
    def speak(self):
        return "Quack!"

duck = Duck()
print(duck.fly())     # Flying!
print(duck.swim())    # Swimming!
print(duck.speak())   # Quack!

⚠️ Warning: Multiple inheritance can lead to complexity. Use it carefully.

Method Resolution Order (MRO)

Python uses MRO to determine which method to call:

python
class A:
    def greet(self):
        return "Hello from A"

class B(A):
    def greet(self):
        return "Hello from B"

class C(A):
    def greet(self):
        return "Hello from C"

class D(B, C):
    pass

d = D()
print(d.greet())  # Hello from B (B comes before C in MRO)
print(D.__mro__)  # Show the order

Practical Example: Employee System

python
class Employee:
    def __init__(self, name, employee_id, salary):
        self.name = name
        self.employee_id = employee_id
        self.salary = salary
    
    def get_details(self):
        return f"{self.name} (ID: {self.employee_id})"
    
    def work(self):
        return f"{self.name} is working"

class Manager(Employee):
    def __init__(self, name, employee_id, salary, department):
        super().__init__(name, employee_id, salary)
        self.department = department
        self.team = []
    
    def add_team_member(self, employee):
        self.team.append(employee)
    
    def get_team_size(self):
        return len(self.team)
    
    def work(self):
        return f"{self.name} is managing the {self.department} department"

class Developer(Employee):
    def __init__(self, name, employee_id, salary, programming_language):
        super().__init__(name, employee_id, salary)
        self.programming_language = programming_language
    
    def work(self):
        return f"{self.name} is coding in {self.programming_language}"

# Create employees
manager = Manager("Alice", "M001", 80000, "Engineering")
dev1 = Developer("Bob", "D001", 60000, "Python")
dev2 = Developer("Charlie", "D002", 65000, "JavaScript")

# Add team members
manager.add_team_member(dev1)
manager.add_team_member(dev2)

# Show details
print(manager.get_details())
print(f"Team size: {manager.get_team_size()}")

print(dev1.get_details())
print(f"Language: {dev1.programming_language}")

# Polymorphism in action
employees = [manager, dev1, dev2]
print("\n--- All employees working ---")
for emp in employees:
    print(emp.work())

Output:

Alice (ID: M001) Team size: 2 Bob (ID: D001) Language: Python --- All employees working --- Alice is managing the Engineering department Bob is coding in Python Charlie is coding in JavaScript

What is Polymorphism?

Polymorphism means "many forms". It allows the same interface (method) to work with different types of objects.

Duck Typing

"If it walks like a duck and quacks like a duck, it's a duck":

python
class Duck:
    def speak(self):
        return "Quack!"

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

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

# Any object with speak() method works
def make_speak(animal):
    return animal.speak()

duck = Duck()
cat = Cat()
dog = Dog()

print(make_speak(duck))  # Quack!
print(make_speak(cat))   # Meow!
print(make_speak(dog))   # Woof!

Polymorphism with Inheritance

python
class Vehicle:
    def move(self):
        pass

class Car(Vehicle):
    def move(self):
        return "Driving 🚗"

class Plane(Vehicle):
    def move(self):
        return "Flying ✈️"

class Boat(Vehicle):
    def move(self):
        return "Sailing 🚤"

# Polymorphic function
def start_journey(vehicle):
    print(f"Starting: {vehicle.move()}")

# Different vehicles, same interface
car = Car()
plane = Plane()
boat = Boat()

start_journey(car)    # Starting: Driving 🚗
start_journey(plane)  # Starting: Flying ✈️
start_journey(boat)   # Starting: Sailing 🚤

isinstance() and issubclass()

Check object and class relationships:

python
class Animal:
    pass

class Dog(Animal):
    pass

class Cat(Animal):
    pass

# Check instance
dog = Dog()
print(isinstance(dog, Dog))      # True
print(isinstance(dog, Animal))   # True (Dog is subclass of Animal)
print(isinstance(dog, Cat))      # False

# Check subclass
print(issubclass(Dog, Animal))   # True
print(issubclass(Cat, Animal))   # True
print(issubclass(Animal, Dog))   # False

Summary

In this tutorial, you learned:

  • ✅ What is inheritance
  • ✅ Creating subclasses
  • ✅ The super() function
  • ✅ Method overriding
  • ✅ Multiple inheritance
  • ✅ What is polymorphism
  • ✅ Duck typing

🧑‍💻 Practice Exercise

Create an inheritance hierarchy for a school system:

  1. Person class (parent) with name, age
  2. Student class that inherits from Person, adds grade
  3. Teacher class that inherits from Person, adds subject
  4. TeachingAssistant that inherits from both Student and Teacher
  5. Use super() to properly initialize all attributes
Click to see solution
python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def get_info(self):
        return f"{self.name}, {self.age} years old"

class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade
    
    def study(self):
        return f"{self.name} is studying for grade {self.grade}"
    
    def get_info(self):
        return f"{self.name}, {self.age} years old, Grade: {self.grade}"

class Teacher(Person):
    def __init__(self, name, age, subject):
        super().__init__(name, age)
        self.subject = subject
    
    def teach(self):
        return f"{self.name} is teaching {self.subject}"
    
    def get_info(self):
        return f"{self.name}, {self.age} years old, Teaches: {self.subject}"

class TeachingAssistant(Student, Teacher):
    def __init__(self, name, age, grade, subject):
        Student.__init__(self, name, age, grade)
        Teacher.__init__(self, name, age, subject)
    
    def get_info(self):
        return f"{self.name}, {self.age} years old, Grade: {self.grade}, TA for: {self.subject}"
    
    def assist(self):
        return f"{self.name} is assisting with {self.subject}"

# Create instances
student = Student("Alice", 16, "10th")
teacher = Teacher("Mr. Smith", 35, "Mathematics")
ta = TeachingAssistant("Bob", 22, "Graduate", "Computer Science")

# Test
print("=== Student ===")
print(student.get_info())
print(student.study())

print("\n=== Teacher ===")
print(teacher.get_info())
print(teacher.teach())

print("\n=== Teaching Assistant ===")
print(ta.get_info())
print(ta.study())
print(ta.teach())
print(ta.assist())

# Show MRO
print(f"\nTeachingAssistant MRO: {TeachingAssistant.__mro__}")

Output:

=== Student === Alice, 16 years old, Grade: 10th Alice is studying for grade 10th === Teacher === Mr. Smith, 35 years old, Teaches: Mathematics Mr. Smith is teaching Mathematics === Teaching Assistant === Bob, 22 years old, Grade: Graduate, TA for: Computer Science Bob is studying for grade Graduate Bob is teaching Computer Science Bob is assisting with Computer Science TeachingAssistant MRO: (<class '__main__.TeachingAssistant'>, <class '__main__.Student'>, <class '__main__.Teacher'>, <class '__main__.Person'>, <class 'object'>)

What's Next

In the next tutorial, we'll learn about OOP - Advanced Concepts - encapsulation, dunder methods, and more.

OOP - Advanced Concepts →

Comments (0)

No comments yet. Be the first to comment!

Leave a comment