Polymorphism — "many forms." The same method or object behaves differently depending on context. Two types: compile-time (static) and run-time (dynamic).
The method to call is resolved at compile time based on signature (name + parameters). Achieved via method overloading. Also called early binding.
Note: return type alone cannot differentiate overloaded methods.
class Calculator {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
}
Calculator calc = new Calculator();
System.out.println(calc.add(5, 3)); // int version
System.out.println(calc.add(5.5, 3.3)); // double version
class Calculator {
public:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
};
Calculator calc;
cout << calc.add(5, 3) << endl; // int version
cout << calc.add(5.5, 3.3) << endl; // double version
class Calculator:
def add(self, a, b):
return a + b # works for both — Python is dynamically typed
calc = Calculator()
print(calc.add(5, 3)) # ints
print(calc.add(5.5, 3.3)) # floats
Keypoint: Compiler chooses the right method at compile time by matching argument types. Faster (early binding). No runtime overhead.
The method to call is resolved at runtime based on the actual object type, not the reference type. Achieved via method overriding. Also called late binding or dynamic method dispatch.
class Animal {
void sound() { System.out.println("Animal makes a sound"); }
}
class Dog extends Animal {
@Override
void sound() { System.out.println("Dog barks"); }
}
Animal ref = new Dog(); // Animal reference, Dog object
ref.sound(); // "Dog barks" — resolved at runtime
class Animal {
public:
virtual void sound() { cout << "Animal makes a sound" << endl; }
};
class Dog : public Animal {
public:
void sound() override { cout << "Dog barks" << endl; }
};
Animal* ptr = new Dog(); // Animal pointer, Dog object
ptr->sound(); // "Dog barks" — vtable lookup at runtime
delete ptr;
class Animal:
def sound(self):
print("Animal makes a sound")
class Dog(Animal):
def sound(self):
print("Dog barks")
myAnimal = Dog()
myAnimal.sound() # "Dog barks" at runtime
Keypoint: JVM/compiler generates code that checks the actual object type at runtime and dispatches to the correct overridden method. Slightly slower (vtable/dispatch table lookup).
| Aspect | Compile-Time | Run-Time |
|---|---|---|
| When resolved | At compile time | At runtime |
| Mechanism | Method overloading | Method overriding |
| Binding | Early (static) | Late (dynamic) |
| Speed | Faster | Slightly slower (dispatch overhead) |
| Inheritance needed? | No | Yes |
It lets you write code that works on a parent reference but calls the child's implementation. This is the foundation of:
List<String> list = new ArrayList<>()
Code trace: What does this print?
class A {
void show() { System.out.println("A"); }
}
class B extends A {
void show() { System.out.println("B"); }
}
class C extends A {
void show() { System.out.println("C"); }
}
A[] arr = {new A(), new B(), new C()};
for (A x : arr) x.show();
Can two overloaded methods differ only by return type?
Polymorphism ⇒ "many forms" ; same method or object reference behaves differently depending on context
Resolution ⇒ resolved at compile time based on method signature
Mechanism ⇒ method overloading (same class, different parameters)
Early binding ⇒ faster execution, no runtime lookup overhead
Restriction ⇒ return type alone cannot differentiate overloaded methods
Resolution ⇒ resolved at runtime based on actual object type
Mechanism ⇒ method overriding (parent and child classes)
Late binding ⇒ vtable / dynamic dispatch lookup
Behavior ⇒ parent reference holding child object invokes child's overridden method
Overloading ⇒ compile-time ; same class ; different parameters
Overriding ⇒ runtime ; parent-child ; exact same parameters
Python ⇒ duck typing ; no compile-time method overloading
C++ ⇒ requires virtual keyword for dynamic dispatch
Java ⇒ all non-static methods are virtual by default
a) Strategy pattern ⇒ swap algorithms at runtime via interface reference
b) Dependency injection ⇒ accept any implementation of a contract
c) Collections ⇒
List<String> list = new ArrayList<>()
Primary source: Oracle Java Tutorials — Polymorphism. Ask me anything that's unclear.
Questions? Ask your agent — you can follow up on any concept, quiz answer, or how this applies to a specific coding problem. Review the Java glossary or syntax quick reference for a compressed overview.