Low-Level Design Tutorial 0/42 lessons ~6 min read Lesson 9

    Polymorphism

    Polymorphism lets one interface invoke different behaviors depending on runtime type.

    Course progress0%
    Focus
    9 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Polymorphism lets one interface invoke different behaviors depending on runtime type. vehicle.requiredSpotType() works for Car and Truck without conditional logic scattered through ParkingLot — cleaner LLD and easier extension.

    Interviewers explicitly test polymorphism when they ask 'how would you add a motorcycle later?' The answer should be a new class, not editing ten switch statements.

    Dynamic dispatch in Java, combined with interfaces and sealed types, is your primary tool for open-ended design problems.

    Understanding the topic

    Key concepts

    • Compile-time polymorphism: method overloading (same name, different params).
    • Runtime polymorphism: overriding — JVM selects implementation by object type.
    • Interface polymorphism: multiple classes implement same interface.
    • Eliminates large switch/if-else on type codes.
    • Works with collections: List holds heterogeneous types.
    • Pattern Strategy is polymorphism applied to interchangeable algorithms.

    Step-by-step explanation

    1. Define common supertype (interface or abstract class).
    2. Implement behavior in each concrete class.
    3. Client code references supertype only.
    4. Add new types by adding classes, not modifying clients (OCP).
    5. Use polymorphic factories when creation also varies.
    6. Combine with double dispatch only when problem requires it (rare in interviews).

    Informative example

    Pricing polymorphism — no switch on customer type in checkout:

    java
    public interface PricingPolicy {
    Money price(Money base, Customer customer);
    }
    public final class RegularPricing implements PricingPolicy {
    @Override
    public Money price(Money base, Customer customer) { return base; }
    }
    public final class MemberPricing implements PricingPolicy {
    @Override
    public Money price(Money base, Customer customer) {
    return base.multiply(0.9);
    }
    }
    public final class Checkout {
    private final PricingPolicy pricing;
    public Checkout(PricingPolicy pricing) { this.pricing = pricing; }
    public Money total(Money base, Customer customer) {
    return pricing.price(base, customer);
    }
    }

    New student discount = new PricingPolicy implementation; Checkout unchanged — classic OCP + polymorphism.

    Real-world use

    Real-world applications

    • Payment methods, fare calculation, chess piece moves.
    • Export formats (JSON, CSV) from same report object.
    • Plugin-style behavior in extensible modules.

    Best practices

    • Replace switch-on-type with polymorphic methods early.
    • Keep polymorphic sets closed with sealed types when appropriate.
    • Test each concrete behavior independently.
    • Avoid instanceof followed by cast when polymorphism fits.
    • Document extension points for new subtypes.

    Common mistakes

    • instanceof chains growing every sprint.
    • Public switch in one method instead of distributed behavior.
    • Overloading confusion — wrong method picked at compile time.
    • Breaking polymorphism by downcasting to concrete types in clients.

    Advanced interview questions

    Interview Prep

    Practice concise answers, then expand each card for the explanation.

    5 questions
    1BeginnerQuestionWhat is polymorphism?+

    Answer

    Same interface, different implementations selected at runtime based on actual object type.
    2BeginnerQuestionOverloading vs overriding?+

    Answer

    Overloading: same class, different signatures. Overriding: subclass replaces superclass instance method.
    3IntermediateQuestionHow does polymorphism help LLD interviews?+

    Answer

    New features add classes instead of editing many conditional blocks.
    4IntermediateQuestionWhen is switch preferable to polymorphism?+

    Answer

    Simple closed enums with trivial behavior and no expected growth.
    5AdvancedQuestionDesign polymorphic fare calculation for cab types.+

    Answer

    FareCalculator interface per CabType implementation; Trip calls calculator.compute(distance, time); add BikeCabCalculator without changing Trip.

    Summary

    Polymorphism defers behavior to subtypes or interface implementations. Eliminates fragile type-switch logic in clients. Supports Open/Closed Principle for new variants. Combine with dependency injection for testability. Prefer behavior on the object over external switches.

    Ready to mark this lesson complete?Track your journey across the entire course.