Polymorphism

  • Explore polymorphism in Python and learn how objects can take multiple forms in OOP.

  • Definition of Polymorphism

    Polymorphism is an Object-Oriented Programming concept where one method, operator, or function can perform different actions based on the object or data type.

    👉 Simple meaning:
    Poly = Many | Morphism = Forms
    ➡️ One name, many behaviors

    Why Do We Use Polymorphism?

    • Makes code flexible and reusable

    • Reduces code duplication

    • Improves scalability

    • Supports dynamic behavior

    • Makes programs easier to maintain

    Real-Life Example

    Teacher

    • In class → teaches

    • In meeting → discusses

    • At home → guides children

    Same person, different behavior
    Basic Syntax of Polymorphism

    class ClassName:

        def method(self):

            pass

    Different classes use the same method name but behave differently.

    Types of Polymorphism in Python

    Python supports 4 main types of polymorphism:

    1. Function Polymorphism

    2. Operator Overloading

    3. Method Overriding

    4. Method Overloading (using default arguments)

    1.Function Polymorphism

    The same function name works with different data types.

Built-in Function Polymorphism

The len() function behaves differently for different data types.

print(len("Python"))      # String
print(len([10, 20, 30]))  # List
print(len({"a": 1, "b": 2}))  # Dictionary
  • 2.Operator Overloading

    Operators behave differently based on operands.

Operator Overloading Example

The + operator adds numbers and concatenates strings.

print(10 + 5)          # Addition
print("Py" + "thon")   # String concatenation

Custom Operator Overloading

This example overloads the + operator using a magic method.

class Book:
    def __init__(self, pages):
        self.pages = pages

    def __add__(self, other):
        return self.pages + other.pages

b1 = Book(100)
b2 = Book(200)
print("Total Pages:", b1 + b2)
  • 3.Method Overriding (Runtime Polymorphism)

    When a child class provides its own implementation of a method already defined in the parent class.

Method Overriding Example

The child class overrides the parent class method.

class Animal:
    def sound(self):
        print("Animal makes a sound")

class Dog(Animal):
    def sound(self):
        print("Dog barks")

class Cat(Animal):
    def sound(self):
        print("Cat meows")

a = Animal()
d = Dog()
c = Cat()

a.sound()
d.sound()
c.sound()
  • 4. Method Overloading (Compile-Time Polymorphism)

    Method overloading is a concept where the same method name is used to perform different tasks by changing the number or type of arguments.

    👉 This concept works in languages like Java and C++.

    Does Method Overloading Work in Python?

    Answer: ❌ NO (Not directly)

    Why Python Does NOT Support Method Overloading (Very Important)

    Python does not support traditional method overloading like Java or C++.

    ❌ What is Traditional Method Overloading?

    Having multiple methods with the same name but different parameters, all existing together:

    add(int a, int b)

    add(int a, int b, int c)

    👉 This is NOT possible in Python.

    Reasons Why Method Overloading Does NOT Work in Python

    1. Python does NOT check method signatures

    • Python identifies methods only by method name

    • It does NOT consider:

      • Number of arguments

      • Type of arguments

    2. Latest method overrides previous ones

    • If the same method name is defined multiple times

    👉 The last method definition replaces earlier ones

❌ Example (Not Overloading)

class Demo:
   def add(self, a, b):
       print(a + b)

   def add(self, a, b, c):
       print(a + b + c)

d = Demo()
d.add(2, 3, 4)
# d.add(2, 3)  ❌ Error
  • Result

    • Only the second add() method exists

    • The first add() method is lost

    • Python keeps only the latest definition

    Then How Do We Achieve Method Overloading in Python?

    👉 Python provides overloading-like behavior, not true overloading.

Method 1: Using Default Arguments

class Calculator:
   def add(self, a, b=0, c=0):
       return a + b + c

calc = Calculator()
print(calc.add(10))
print(calc.add(10, 20))
print(calc.add(10, 20, 30))
  • Explanation

    • Same method name

    • Different number of arguments

    • Works like method overloading

Method 2: Using Variable-Length Arguments (*args)

class Calculator:
   def add(self, *nums):
       return sum(nums)

c = Calculator()
print(c.add(5, 10))
print(c.add(5, 10, 15))
print(c.add(5, 10, 15, 20))
  • Explanation

    • *args accepts any number of arguments

    • Allows flexible method behavior

Polymorphism with Inheritance Example

Different child classes use the same method name with different behavior.

class Shape:
    def area(self):
        pass

class Rectangle(Shape):
    def area(self):
        print("Area = length × breadth")

class Circle(Shape):
    def area(self):
        print("Area = π × r²")

r = Rectangle()
c = Circle()

r.area()
c.area()
  • Polymorphism vs Method Overriding

    Polymorphism

    Method Overriding

    General OOP concept

    Specific implementation

    One name, many forms

    Child replaces parent method

    Can occur without inheritance

    Requires inheritance