Overriding
Inheriting a method as-is is only half the story — a SavingsAccount needs withdraw to behave differently from its parent, not identically. A subclass can replace an inherited method by redefining it with the same signature. That is overriding (different from overloading in lesson 4-2, which was same name, different parameters).
class Animal { void speak() { System.out.println("..."); } } class Dog extends Animal { @Override void speak() { System.out.println("woof"); } }
Now the payoff, polymorphism: a variable of type Animal may hold any animal, and Java picks the method of the object's actual class at runtime:
Animal pet = new Dog(); pet.speak(); // woof, not ...
One loop over Animal[] can make every species speak correctly without a single if-statement.
Code exercise · java
Run this. The array is typed Animal[], yet each element speaks in its own voice. This dispatch-by-actual-class is polymorphism.
Quiz
Animal pet = new Cat(); pet.speak(); Which speak runs, and when is that decided?
instanceof: asking what an object really is
A variable typed Animal only exposes Animal's methods — even when the object inside is a Dog, pet.fetch() will not compile, because the compiler can only trust the declared type. When you genuinely need the specific type back, instanceof tests what the object actually is, and its pattern form gives you a correctly-typed variable in one step:
Animal pet = new Dog(); pet instanceof Dog // true — asks about the object, not the variable if (pet instanceof Dog d) { // test + cast in one move d.fetch(); // d is a Dog here }
Use it sparingly: a chain of instanceof checks choosing behavior per type is usually a sign the behavior should be an overridden method instead — that is what polymorphism is for.
Code exercise · java
Run this. The object is a Dog no matter what the variable's declared type says, so both instanceof tests pass, and the pattern form hands you a Dog-typed d that can fetch.
Code exercise · java
Your turn. Shape has a method area() returning 0.0. Square (side) and Rect (width, height) extend it and override area(). Loop over the Shape[] with an enhanced for (lesson 3-3), sum the areas, and print `total area: 17.0`.