Chapter 12: Polymorphism

Polymorphism is one of the four pillars of OOP and literally means “many forms”. It allows one interface / method name to behave differently depending on the object that is calling it.

Imagine we’re sitting together in a quiet corner of your favorite Mumbai café — it’s evening, the rain is gently tapping outside, and I’m going to explain polymorphism like I’m teaching my best friend who’s just starting to feel the real beauty of Java.

We’ll go super slowly, with lots of real-life analogies, complete runnable programs, step-by-step breakdowns, tables, common mistakes with fixes, and plenty of examples you can copy-paste and run right now.

Let’s dive in!

1. What is Polymorphism? (The Big Idea)

Polymorphism allows us to use one method name (or reference type) to invoke different implementations based on the actual object type at runtime.

There are two main types of polymorphism in Java:

Type When it happens Achieved by Also called
Compile-time At compile time Method Overloading Static / Early binding
Runtime At runtime Method Overriding Dynamic / Late binding

2. Compile-time Polymorphism (Method Overloading)

Method Overloading:

  • Same method name
  • Different parameters (number, type, or order)
  • Happens inside the same class (or inherited)
  • Compiler decides which method to call based on the arguments at compile time

Real-life analogy: A remote control has a “Power” button.

  • If you press it once → TV turns on
  • If you press it twice quickly → TV turns off Same button name → different actions based on how you use it.

Example 1: Overloading in a Calculator class

Java

Test it:

Java

Output:

text

Important: Return type does not matter for overloading — only parameters count!

3. Runtime Polymorphism (Method Overriding + Upcasting)

Method Overriding (already introduced in Chapter 11):

  • Child class redefines a method that exists in the parent class
  • Same name, same parameters, same return type (or covariant return)
  • @Override annotation is recommended

Runtime polymorphism happens when:

  • We create a parent reference pointing to a child object (called upcasting)
  • We call an overridden method → Java decides at runtime which version to execute (based on actual object type)

Real-life analogy: A remote control says “Play”.

  • If connected to a TV → plays video
  • If connected to a music system → plays song Same button → different action depending on what device is actually connected.

Example 2: Classic Animal Sound Example

Java

Test Runtime Polymorphism (Upcasting):

Java

Output:

text

4. Upcasting and Downcasting

Upcasting (safe, automatic):

  • Child object is treated as Parent type
  • Always allowed (no explicit cast needed)
Java

Downcasting (dangerous, needs explicit cast):

  • Treating a Parent reference back to Child type
  • Only safe if the object is actually of that child type
Java

Safe way to downcast — use instanceof:

Java

5. Quick Recap Table (Your Cheat Sheet)

Concept How it Works When Decided Example
Compile-time Polymorphism Method Overloading Compile time add(int,int) vs add(double,double)
Runtime Polymorphism Method Overriding + Upcasting Runtime animal.sound() calls correct version
Upcasting Parent reference → Child object Automatic Animal a = new Dog();
Downcasting Child reference ← Parent reference Explicit cast Dog d = (Dog) animal;

6. Common Mistakes & Fixes

Mistake Problem Fix
Using == instead of .equals() Wrong comparison Always .equals() for objects
Forgetting @Override Risk of accidental overload Add @Override — compiler warns
Downcasting without instanceof ClassCastException at runtime Check with instanceof first
Changing parameter type in override Not overriding — overloading instead Keep exact same signature
Overriding static methods Hiding, not overriding Static methods cannot be overridden

7. Real-World Example: Payment System (Polymorphism in Action)

Java

Test:

Java

Output:

text

Homework for You (Practice to Master!)

  1. Basic: Create Shape abstract class with draw() method. Create Circle, Rectangle, Triangle — override draw().
  2. Medium: Make an array of Animal objects (Dog, Cat, Cow) — loop and call sound().
  3. Advanced: Create BankAccount (deposit(), withdraw()) → SavingsAccount, CurrentAccount override withdraw() with different overdraft rules.
  4. Challenge: Fix this buggy code:
    Java
  5. Fun: Create a MediaPlayer interface with play() → implement in VideoPlayer, AudioPlayer, MusicPlayer.

You’re doing fantastic! Polymorphism is what makes Java code flexible, reusable, and elegant — now you can write code that works with any object in a family!

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *