11 · 32 · 6 min
Polymorphism: the same call, different code
One call, and which code runs is decided by the object rather than by the variable.
class Animal { void speak() { System.out.print("generic"); } }
class Dog extends Animal { void speak() { System.out.print("woof"); } }
Animal a = new Dog();
a.speak(); // woofThe variable is declared Animal. The object is a Dog. Dog.speak runs. This is dynamic dispatch, decided at runtime.
Overriding is not overloading
| Overriding | Overloading | |
|---|---|---|
| Where | Subclass replaces parent's method | Same class, several versions |
| Signature | Identical | Different parameters |
| Decided | At runtime, by the object | At compile time, by the arguments |
| Purpose | Behave differently | Accept different inputs |
void print(int x) { } // overloading: chosen by argument type
void print(String s) { }The static trap
class Parent { static void greet() { System.out.print("parent"); } }
class Child extends Parent { static void greet() { System.out.print("child"); } }
Parent p = new Child();
p.greet(); // prints "parent"Static methods belong to the class, so there is no object to dispatch on. The call is bound at compile time from the declared type. This is hiding, not overriding, and it is why calling a static method through an instance is bad style: it reads as though it depends on the object and it does not.
Fields behave the same way: they are hidden, never overridden.