Polymorphism

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

TL;DR

  • Polymorphism means “many forms”. It allows objects of different classes to be treated as objects of a common superclass.
  • It enables a single interface or method name to represent different underlying behaviors.
  • There are two types: Compile-time (Method Overloading) and Runtime (Method Overriding / Dynamic Method Dispatch).

Concept

The most powerful aspect of Polymorphism in Java is Runtime Polymorphism.

When a parent reference variable points to a child object (e.g., Animal a = new Dog()), and you call a method on that reference, the JVM determines at runtime which overridden method to call based on the actual object type (Dog), not the reference type (Animal).

Examples

class Animal {
    public void makeSound() {
        System.out.println("Some generic animal sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark!");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        // Parent Reference pointing to Child Objects
        Animal myDog = new Dog();
        Animal myCat = new Cat();
        
        // The JVM dynamically calls the overridden methods at runtime!
        myDog.makeSound(); // Outputs: Bark!
        myCat.makeSound(); // Outputs: Meow!
        
        // This makes code highly extensible:
        Animal[] pets = {new Dog(), new Cat(), new Animal()};
        for (Animal pet : pets) {
            pet.makeSound(); 
        }
    }
}

Interview Questions

Q: What is the difference between Compile-time and Runtime Polymorphism?
A: - Compile-time Polymorphism (Static Binding): Achieved through Method Overloading. The compiler knows exactly which method to call based on the number and type of arguments passed.

  • Runtime Polymorphism (Dynamic Binding): Achieved through Method Overriding. The compiler does not know which method will be executed; it is determined by the JVM at runtime based on the actual object instantiated on the heap.

Q: Can we achieve runtime polymorphism by overriding data members (fields)?
A: No. Variables are not polymorphic in Java. Runtime polymorphism only applies to instance methods. If a child class hides a parent’s field by declaring a field with the same name, the field accessed is determined entirely by the reference type at compile time, not the object type.