Polymorphism lets you treat different objects through the same interface or superclass. Calling an overridden method on a base reference uses dynamic dispatch to run the concrete implementation at runtime; overloading provides compile‑time polymorphism.
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.sound(); // Output: Dog barks
}
}