What is Polymorphism?
Polymorphism is one of the core principles of object-oriented programming. The word polymorphism means "many forms". In programming, it refers to the ability of different classes or objects to respond to the same method name or operator in different ways.
Polymorphism allows you to write more flexible, extensible, and maintainable code. Instead of writing multiple versions of a method or function for each object type, you can write a single interface and have multiple implementations.
Types of Polymorphism
- Compile-Time Polymorphism (Static Binding): Achieved using method overloading or operator overloading.
- Run-Time Polymorphism (Dynamic Binding): Achieved using method overriding and inheritance.
Example 1: Compile-Time Polymorphism (Method Overloading)
Suppose we want a function that can add either two or three numbers. Instead of writing differently named functions, we use the same function name with different parameters.
class Calculator:
function add(a, b):
return a + b
function add(a, b, c):
return a + b + c
obj = Calculator()
print(obj.add(2, 3)) # Should call the two-parameter version
print(obj.add(1, 2, 3)) # Should call the three-parameter version
Output:
5 6
But wait... How does the system know which version to run?
That’s where compile-time binding comes in. The compiler checks the number of arguments and calls the appropriate version of the function before the program runs.
Example 2: Run-Time Polymorphism (Method Overriding)
Imagine we have a base class Shape
with a method area()
. Different shapes like Circle and Rectangle can override this method to calculate their specific area.
class Shape:
function area():
return 0
class Circle inherits Shape:
function area():
return 3.14 * radius * radius
class Rectangle inherits Shape:
function area():
return length * width
# Using polymorphism
function printArea(shapeObject):
print(shapeObject.area())
obj1 = Circle(radius=5)
obj2 = Rectangle(length=4, width=6)
printArea(obj1) # Circle's area
printArea(obj2) # Rectangle's area
Output:
78.5 24
Question: Why use polymorphism when we can just call circle.area()
or rectangle.area()
directly?
Great question! The power of polymorphism lies in abstraction. You can write code that works on the Shape
interface without knowing the actual type of the object. This makes your code more reusable and easier to extend.
Real-World Analogy
Consider a remote control (interface). It can control a TV, AC, or Music System (different classes). The same button (method) might perform different actions depending on the device—this is polymorphism in action.
Example 3: Polymorphism with Collections
You can store objects of different subclasses in a single collection and invoke methods on them polymorphically.
shapes = [Circle(radius=3), Rectangle(length=5, width=2), Circle(radius=1)]
for shape in shapes:
print(shape.area())
Output:
28.26 10 3.14
Summary
- Polymorphism enables one interface to be used for a general class of actions.
- It promotes code reuse, readability, and flexibility.
- Two main types: compile-time (method overloading) and run-time (method overriding).
- It’s a foundational principle in object-oriented design and architecture.
Questions to Develop Intuition
- Q: Can we override static methods or overloaded methods at runtime?
A: No. Overloading is resolved at compile time. Overriding is resolved at runtime. - Q: Why is run-time polymorphism considered more powerful?
A: Because it enables dynamic behavior and decouples method calls from specific class implementations. - Q: What if I have 10 different shape classes. Do I need to write 10 different area functions?
A: No. Each shape class overrides the same method name, and polymorphism ensures the correct one is called.