Skip to main content

🎭 Polymorphism

One interface, many implementations

The Remote Control Analogy

You have ONE universal remote control. It has a "Power" button.

  • Point at TV → Press Power → TV turns on
  • Point at Sound Bar → Press Power → Sound Bar turns on
  • Point at Streaming Box → Press Power → Streaming Box turns on

Same button, different devices, different actions.

But from your perspective, you're just pressing "Power" - you don't care HOW each device handles it.

That's polymorphism!

The same method name (power()) produces different behavior depending on which object receives it. The remote doesn't need to know if it's a TV or Sound Bar - it just calls power() and the device handles it.


Why Polymorphism Matters

The Problem: Different Types, Same Action

Imagine building a drawing app. You have:

  • Circle
  • Rectangle
  • Triangle

Each shape calculates its area differently:

  • Circle: Ď€ Ă— r²
  • Rectangle: width Ă— height
  • Triangle: ½ Ă— base Ă— height

Without polymorphism:

if (shape is Circle) {
    return π × radius²
} else if (shape is Rectangle) {
    return width Ă— height
} else if (shape is Triangle) {
    return ½ × base × height
}
// What if we add 20 more shapes?
// 20 more if statements!

With polymorphism:

shape.getArea()  // Just call it - each shape knows its own formula

Add a new shape? It just works. No if-statements to update.


How Polymorphism Works

Each object type implements the SAME method in its OWN way:

Dog.speak()    → "Woof!"
Cat.speak()    → "Meow!"
Duck.speak()   → "Quack!"

From the outside, you just call speak() on any animal. Each animal knows how to respond.

The magic:

animals = [Dog, Cat, Duck]

for each animal in animals:
    animal.speak()  // Computer figures out WHICH speak() to use

Output:
"Woof!"
"Meow!"
"Quack!"

You don't check types. You don't use if-statements. Each object knows its own behavior.


Real-World Examples

1. Payment Processing

Different payment methods, same action:

CreditCard.process(amount) → Charges credit card
PayPal.process(amount)     → Uses PayPal
Crypto.process(amount)     → Sends cryptocurrency

Checkout code:

processor.process(totalAmount)  // Works across many payment types

2. Notifications

Different channels, same action:

Email.send(message)     → Sends email
SMS.send(message)       → Sends text
Push.send(message)      → Sends app notification

3. Export Formats

Different formats, same action:

PDF.export(data)        → Creates PDF file
Excel.export(data)      → Creates spreadsheet
CSV.export(data)        → Creates CSV file

4. Game Characters

Different characters, same action:

Warrior.attack()        → Sword slash
Mage.attack()           → Cast spell
Archer.attack()         → Shoot arrow

The Power: Easy to Extend

Without polymorphism, adding a new payment type means:

  1. Create new class
  2. Find ALL places with if-statements
  3. Add new case to each one
  4. Hope you didn't miss any

With polymorphism, adding a new payment type means:

  1. Create new class with process() method
  2. Done! It just works everywhere

This is the Open/Closed Principle: open for extension, closed for modification.


Duck Typing: "If It Quacks Like a Duck..."

In JavaScript, you don't even need formal inheritance:

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

Objects just need to have the right methods - they don't need a common parent:

dog = { speak() { return "Woof!" } }
robot = { speak() { return "Beep boop!" } }
alien = { speak() { return "Greetings!" } }

// All work, no inheritance needed!
for each thing:
    thing.speak()

As long as the method exists, it works.


Types of Polymorphism

TypeWhat It MeansExample
Runtime (Override)Same method, different classesDog.speak() vs Cat.speak()
Compile-time (Generics)Same code, different typesArray<String> vs Array<Number>
Ad-hoc (Overload)Same name, different parametersadd(int, int) vs add(float, float)

Runtime polymorphism (method overriding) is the most common and what people usually mean by "polymorphism."


Common Mistakes

Mistake 1: Checking Types Manually

// ❌ Defeats the purpose of polymorphism!
if (animal instanceof Dog) { ... }
else if (animal instanceof Cat) { ... }

// âś“ Let polymorphism do its job
animal.speak()

Mistake 2: Assuming Implementation Details

// ❌ Assumes it's a Circle
function getRadius(shape) {
    return shape.radius   // Rectangle doesn't have radius!
}

// âś“ Use the polymorphic interface
function getArea(shape) {
    return shape.getArea()  // All shapes have this!
}

Mistake 3: Not Following the Contract

If you say an object can speak(), it should have a speak() method:

// ❌ Broke the contract!
class Mime extends Performer {
    // Forgot to implement speak()!
}

FAQ

Q: Polymorphism vs Inheritance?

Inheritance is HOW you create the hierarchy (extends). Polymorphism is WHAT happens when you call methods on those objects (same method, different behavior).

Q: Can I have polymorphism without inheritance?

Yes! In JavaScript, duck typing means any object with the right methods will work. No common parent needed.

Q: What is an interface?

A contract that says "objects of this type should have these methods." TypeScript and Java have formal interfaces.

Q: Why is polymorphism useful for testing?

You can swap real objects with "mock" objects that have the same methods. Test without hitting real databases or APIs.

Q: Is operator overloading polymorphism?

Yes! In Python, + works differently for numbers vs strings. That's ad-hoc polymorphism.

Q: What is the Liskov Substitution Principle?

Child classes should work anywhere the parent class works. Good polymorphism follows this.


Summary

Polymorphism lets different objects respond to the same method call in their own way. It's a cornerstone of flexible, extensible code.

Key Takeaways:

  • Same method name, different behavior per object type
  • Eliminates type-checking if-statements
  • Makes code easy to extend (add types without changing existing code)
  • Duck typing: if it has the method, it works
  • Makes testing easier with mock objects
  • Core principle of object-oriented programming

Think of it this way: you tell objects WHAT to do, they decide HOW to do it!

Leave a Comment

Comments (0)

Be the first to comment on this concept.

Comments are approved automatically.