2.1.11 · D3OOP Fundamentals

Worked examples — Method overriding — when and why

4,655 words21 min readBack to topic

This page is one big practice arena. The parent note built the idea of overriding (same signature, real object wins, chosen at runtime). Here we hit every kind of situation overriding can throw at you — the clean cases and the traps. Before each example, you forecast the answer, then we grind through it.


The scenario matrix

Every row is a "case class" this topic can produce. Each worked example below is tagged with the cell it covers, and every example carries its own figure.

# Case class What makes it tricky Example
A Pure specialize child totally replaces parent body Ex 1
B Extend with super child adds to parent body Ex 2
C Dispatch through base variable declared type ≠ real type Ex 3
D Overload look-alike (NOT override) different params → picked at compile time Ex 4
E Abstract contract (degenerate base) parent body is empty/forbidden Ex 5
F Static "override" trap (hiding) no dynamic dispatch happens Ex 6
G Liskov limit (narrowing = illegal) override must stay substitutable Ex 7
H Real-world word problem many shapes, one loop, zero if/else Ex 8
I Degenerate/limiting input zero radius, empty list Ex 9
J Exam-style twist mixed override + overload + super in one trace Ex 10
K Blocked override (final / sealed) parent forbids overriding at all Ex 11

Prerequisites you may want open: Inheritance, Polymorphism, Method overloading, Abstract classes and interfaces, Liskov Substitution Principle, Open-Closed Principle, super keyword. (These are cross-links to sibling notes in the same study vault — click one to review that concept if a word here feels new.)


Example 1 — Pure specialize (cell A) · 🟦 Python


Example 2 — Extend with super (cell B) · 🟦 Python


Example 3 — Dispatch through a base-typed variable (cell C) · 🟦 Python


Example 4 — Overload look-alike, NOT override (cell D) · 🟧 Java-style


Example 5 — Abstract contract, degenerate base body (cell E) · 🟦 Python


Example 6 — Static "override" trap = hiding (cell F) · 🟧 Java-style


Example 7 — Liskov limit: narrowing is illegal (cell G) · 🟧 Java-style (Java 5+)


Example 8 — Word problem: billing many shapes, zero if/else (cell H) · 🟦 Python


Example 9 — Degenerate / limiting inputs (cell I) · 🟦 Python


Example 10 — Exam twist: override + overload + super in one trace (cell J) · 🟦 Python


Example 11 — Blocked override: final / sealed (cell K) · 🟧 Java / C#


Recall

Runtime type of the object decides which override runs ::: Yes — the declared/static type only controls whether the call compiles (in typed languages). A method's signature is ::: its name plus the number/order/types of its parameters (return type usually excluded). How does Python find which area to run? ::: It walks the object's class MRO (e.g. Circle → Shape → object) and takes the first match — not a fixed vtable. A zero-radius circle's overridden area() ::: 0 (no special case needed). Static method redeclared in a child ::: Hidden, resolved by declared type at compile time — not overridden. Calling a static via an instance (b.who()) is dangerous because ::: it compiles but resolves by declared type, hiding behaviour and misleading readers. super().greet() inside an override ::: Deliberately runs the parent's body, then the child adds to it. When did Java allow covariant return types, and who enforces them? ::: Java 5+; the compiler checks the child's return is a subtype of the parent's. Legal way to "tighten" an override's return type ::: Return a subtype (covariant return) — never narrow access. Overriding a final (Java) / sealed (C#) method ::: Impossible — it is a compile-time error; the parent forbids it to protect an invariant. Why sum([]) returns 0 and not None ::: sum starts from the additive identity 0 and adds nothing, so it returns that 0.