OBJECT-ORIENTED FOUNDATIONS / OBJECT DESIGN BRIEF

Polymorphism

Polymorphism means 'many forms': the same call behaves differently depending on the actual object.

BeginnerPhase 01 / Topic 5 of 7ResponsibilitiesCollaborationsExtensibility
01

Overview

Polymorphism means 'many forms': the same call behaves differently depending on the actual object. When code calls shape.area(), a Circle and a Rectangle each run their own implementation. The caller works with the common type and never checks which concrete type it has.

Runtime (subtype) polymorphism comes from interfaces and overriding and is the one that matters most in design: it replaces switch-on-type code, supports the Open-Closed Principle, and powers nearly every design pattern. Compile-time polymorphism includes method overloading and generics.

The 'play' button

Pressing play on a music app, a video player, or a game console all 'play', but each does something different. You do not need to know the device's internals to press play.

02

When to use it

  • Code switches on a type or enum to decide behavior.
  • New variants will be added over time.
  • Collections of different but related objects processed uniformly.
03

Where it shows up in interviews

Replace conditional with polymorphism

Recognize it when: switch(type) repeated in several places.

  • Design a payment system
  • Design a notification service
Uniform processing

Recognize it when: iterate over mixed items (shapes, vehicles, employees).

  • Design a drawing app
  • Design payroll for employee types
04

Where it is used in real software

java.util.List

Code written against List works with ArrayList, LinkedList, or immutable lists.

Plugins

IDE and browser extensions implement shared interfaces the host calls polymorphically.

Web frameworks

Express middleware and Spring filters are all called the same way but do different work.

05

Key terms

Subtype polymorphism
One interface, many implementations, chosen at runtime.
Dynamic dispatch
The runtime picks the method based on the actual object.
Overloading
Same name, different parameter lists (compile time).
Parametric polymorphism
Generics: List<T> works for any T.
06

How it works, step by step

  1. 1
    Spot the type switch

    if (type === 'circle') ... else if ...

  2. 2
    Define the common operation

    area(): number.

  3. 3
    Move each branch into its type

    Circle.area(), Rectangle.area().

  4. 4
    Call through the common type

    shapes.map(s => s.area()).

  5. 5
    Add new types without editing callers

    Triangle implements Shape.

07

Switch vs polymorphism

Computing pay for full-time, contractor, and intern

Step 1 / 3
Concernswitch(employee.type)Polymorphic pay()
Add a new typeEdit every switchAdd one class
Forgotten branchSilent bug or defaultCompile error: must implement pay()
TestingTest giant methodTest each class

NOWConcern: Add a new type | switch(employee.type): Edit every switch | Polymorphic pay(): Add one class

Polymorphism moves the decision into the type system; the switch disappears from business code.

08

Implementation

interface Employee {  name: string;  monthlyPay(): number;} class FullTime implements Employee {  constructor(readonly name: string, private salary: number) {}  monthlyPay() { return this.salary / 12; }} class Contractor implements Employee {  constructor(readonly name: string, private hourly: number, private hours: number) {}  monthlyPay() { return this.hourly * this.hours; }} class Intern implements Employee {  constructor(readonly name: string, private stipend: number) {}  monthlyPay() { return this.stipend; }} const staff: Employee[] = [new FullTime("Ana", 120_000), new Contractor("Bo", 80, 120), new Intern("Cy", 2_000)];const payroll = staff.reduce((sum, e) => sum + e.monthlyPay(), 0); // no type checks
09

Complexity and performance

Dynamic dispatchO(1)

Indirect call.

Adding a type1 class

No caller changes.

10

Trade-offs

Adding types vs adding operations

Polymorphism makes new types easy but new operations require changing every class; the Visitor pattern flips this.

Readability

Behavior is spread across classes; an IDE is needed to find all implementations.

11

Variants and related techniques

Pattern matching on sealed types

Java 21 switch and TypeScript unions give exhaustive checks when operations change more than types.

Duck typing

Python and JavaScript dispatch on whatever methods an object has.

12

Common mistakes

  • instanceof checks after introducing an interface.

    Fix: Move the behavior into the interface.

  • Overloading confused with overriding.

    Fix: Overloads are chosen at compile time by static type, not the runtime object.

13

Interview questions

How does polymorphism support the Open-Closed Principle?

Callers depend on an interface, so new behavior is added by writing a new implementation rather than modifying existing callers.

Overloading vs overriding?

Overloading: same method name with different parameters, resolved at compile time. Overriding: a subclass replaces a parent method, resolved at runtime by the actual object.

14

Practice problems

ProblemDifficultyWhat it trains
Replace a notification-type switch with polymorphismEasyRefactoring.
Design shapes with area and perimeterEasyInterfaces.