Skip to content

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.

java
class Animal { void speak() { System.out.print("generic"); } }
class Dog extends Animal { void speak() { System.out.print("woof"); } }

Animal a = new Dog();
a.speak();               // woof

The variable is declared Animal. The object is a Dog. Dog.speak runs. This is dynamic dispatch, decided at runtime.

Overriding is not overloading

OverridingOverloading
WhereSubclass replaces parent's methodSame class, several versions
SignatureIdenticalDifferent parameters
DecidedAt runtime, by the objectAt compile time, by the arguments
PurposeBehave differentlyAccept different inputs
java
void print(int x)    { }     // overloading: chosen by argument type
void print(String s) { }

The static trap

java
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.