Polymorphism
Polymorphism means many forms. In OOP, it lets one piece of code work with many different types as long as they share a common interface. You write a function that calls shape.area() and it doesn't care whether the shape is a circle, square, or triangle — each shape knows how to compute its own area.
Why It Matters
Without polymorphism, code that handles different types ends up with long if/else chains:
if shape_is_circle: ...
elif shape_is_square: ...
elif shape_is_triangle: ...
Every time you add a new shape, you have to find and update every one of those chains. With polymorphism, you just create a new class with its own area() method — existing code keeps working unchanged. This is the open/closed principle in action.
How It Works
Each subclass overrides the same method. When you call that method on an instance, the language looks up the actual type of the object at runtime and runs that type's version. This is called dynamic dispatch.
In C++, you opt in by marking methods virtual. In Java, methods are virtual by default. In Python and JavaScript, all method calls are dynamically dispatched.
Duck Typing
Python and JavaScript take polymorphism one step further with duck typing: "if it walks like a duck and quacks like a duck, it's a duck." You don't need a shared base class — any object that has the right methods works. If your function calls obj.area(), anything with an area() method can be passed in.
Polymorphism vs Overloading
Don't confuse runtime polymorphism (one method, many types) with overloading (multiple methods with the same name but different parameter lists). Overloading is resolved at compile time. Polymorphism is the runtime mechanism that makes inheritance powerful.
Try It Yourself
- Add a
Rectangleshape to the example. Notice no other code needs to change. - Write a
total_area(shapes)function that sums areas of any list of shapes - Build an
Animalhierarchy withDog,Cat,Cowand callspeak()on a list of them