Inheritance, Polymorphism & Inner Classes in Python
In this note, we explore the remaining two core pillars of Object-Oriented Programming (Inheritance and Polymorphism) along with Inner (Nested) Classes.
1. Principle 3: Inheritance in Python
Inheritance is the mechanism by which a new class (Child / Derived / Subclass) acquires all the attributes and methods of an existing class (Parent / Base / Superclass).
- Main Benefit: Code Reusability — write common code once in the Parent class and reuse it across multiple Child classes!
Syntax of Inheritance in Python:
Instead of keywords like extends (in Java), Python passes the Parent class inside parentheses ( ):
class Parent:
# parent methods
class Child(Parent):
# child inherits everything from Parent
Types of Inheritance in Python
Unlike Java, Python directly supports Multiple Inheritance using classes!
↓
Child B
↓
Parent B → Child C
↘ ↙
Child C
↙ ↘
Child B Child C
Example — Inheritance and the super() Function:
The built-in super() function is used inside a Child class to call the constructor (__init__) or methods of its Parent class.
# Parent Class
class Person:
def __init__(self, name):
self.name = name
def show_name(self):
print("Name:", self.name)
# Child Class inheriting from Person
class Employee(Person):
def __init__(self, name, emp_id, salary):
super().__init__(name) # Calls Parent class constructor
self.emp_id = emp_id
self.salary = salary
def show_details(self):
self.show_name() # Reusing Parent method
print(f"ID: {self.emp_id} | Salary: Rs.{self.salary}")
emp = Employee("Vikram", "EMP105", 45000)
emp.show_details()
Example — Multiple Inheritance (class Child(Father, Mother)):
class Father:
def skill_driving(self):
print("Knows Car Driving")
class Mother:
def skill_painting(self):
print("Knows Oil Painting")
# Child inherits from BOTH Father and Mother
class Child(Father, Mother):
pass
c = Child()
c.skill_driving()
c.skill_painting()
2. Principle 4: Polymorphism in Python
The word Polymorphism comes from Greek (Poly = Many, Morphs = Forms). It means the same function name or operator behaving differently depending on the object or data type.
Ways Polymorphism Works in Python:
A. Built-in Polymorphism (Operator & Function Overloading)
- The
+operator performs arithmetic addition for numbers (10 + 20 = 30), but performs concatenation for strings ("Hello " + "World"). - The
len()function counts characters in a string (len("BCA") = 3), items in a list (len([10, 20]) = 2), or keys in a dictionary.
B. Method Overriding (Runtime Polymorphism)
When a Child class provides its own specific implementation of a method that is already defined in its Parent class, it is called Method Overriding.
class Animal:
def sound(self):
print("Animal makes a sound")
class Dog(Animal):
# Overriding parent's sound() method
def sound(self):
print("Dog Barks: Woof Woof!")
class Cat(Animal):
# Overriding parent's sound() method
def sound(self):
print("Cat Meows: Meow!")
# Polymorphism in action: same method call behaves differently!
for pet in [Dog(), Cat()]:
pet.sound()
3. Inner Classes (Nested Classes) in Python
An Inner Class (or Nested Class) is a class defined entirely inside the body of another class (the Outer Class).
Why Use Inner Classes?
- Logical Grouping: When one class is tightly coupled with another class and has no meaning outside it (for example, a
Laptopclass having an innerCPUclass, or aStudentclass having an innerAddressorDOBclass). - Better Encapsulation & Organization: Keeps helper classes hidden inside the main outer class.
Example of Inner Class in Python:
class Student: # Outer Class
def __init__(self, name, roll_no, brand, ram):
self.name = name
self.roll_no = roll_no
# Creating object of Inner Class inside Outer Class constructor
self.lap = self.Laptop(brand, ram)
def show_student(self):
print(f"Student: {self.name} (Roll: {self.roll_no})")
self.lap.show_laptop()
class Laptop: # Inner Class (inside Student)
def __init__(self, brand, ram):
self.brand = brand
self.ram = ram
def show_laptop(self):
print(f"Laptop Specs: {self.brand}, {self.ram}GB RAM")
# Creating Outer Class object automatically initializes Inner Class object
s1 = Student("Karan", 101, "Dell Inspiron", 16)
s1.show_student()
Output:
Student: Karan (Roll: 101)
Laptop Specs: Dell Inspiron, 16GB RAM
(Note: You can also create an Inner Class object directly from outside using lap_obj = Student.Laptop("HP", 8)).