Polymorphism — One interface, many behaviours
One interface, many implementations — callers stay dumb. · Avoid instanceof chains; dispatch through the interface.
Watch
Watch, then scroll down for code and practice.
In code
interface Payment {
authorize(amount: number): boolean;
}
class CardPay implements Payment {
authorize(amount: number) {
return amount < 10_000;
}
}
class UpiPay implements Payment {
authorize() {
return true;
}
}
function checkout(p: Payment, amt: number) {
if (!p.authorize(amt)) throw new Error("declined");
}📘 Key ideas
Runtime polymorphism
A parent reference holds a child object. The actual method called is determined at runtime — this is dynamic dispatch.
The litmus test
If your code has instanceof checks or type-switch logic, your design is wrong. Good polymorphism means the caller never needs to know the concrete type.
Open for extension
Add new payment methods (Crypto, BNPL) without touching Checkout.processPayment() — just add a new class that implements Payment.
Compile-time polymorphism
Method overloading — same name, different parameter types. Less powerful but sometimes useful for convenience APIs.
🧠 Practice — Apply What You Learned
🚀 Now apply what you learned
Pick a problem above, write your solution, and get AI feedback on your design.
Start Practice →