Matheion

MA-JAVA0 · Module 15

Class inheritance, super, and overriding

Topics: extends · super · @Override · Substitution

Overview

Session 15 — Class inheritance, super, and overriding

Subclassing lets you say “this type is a specialised kind of that type.” You reuse fields and behaviour from a superclass, specialise with extra state, and replace individual methods through overriding while still calling super when you want layered behaviour. This session separates overriding (runtime choice) from overloading (compile-time choice) and shows why @Override belongs on every replacement method.

Time: about 95 minutes.

Concepts

1. The extends keyword

A class may subclass exactly one other class (Java has single inheritance for implementation):

public class AlarmClock extends Clock {
    // AlarmClock is-a Clock; inherits visible members
}

The subclass inherits non-private members of the superclass. Constructors are not inherited—you must route initialization through super(...) or an implicit default super-call.


2. Constructors chain with super(...)

If you write no constructor, the compiler inserts a default that calls super(). If you write a constructor, the first statement must be this(...) or super(...):

public AlarmClock(String zone, int volume) {
    super(zone); // Clock(String) runs first
    this.volume = volume;
}

If the superclass has no zero-arg constructor, every subclass constructor must explicitly call a visible super(...).


3. Overriding and @Override

Overriding replaces a runtime-selected implementation when the receiver’s dynamic type is the subclass:

@Override
public String summary() {
    return super.summary() + " vol=" + volume;
}

Always annotate with @Override. If the superclass method is renamed, your “override” without the annotation can silently turn into an overload or a dead method—@Override makes that a compile error.


4. Overloading is not overriding

Two methods in the same class (or inherited visible) with the same name but different parameter lists are overloads. The compiler picks by static types of arguments at the call site. Overriding depends on @Override-compatible signatures and dynamic dispatch on the object’s actual class.


5. protected visibility

protected members are visible to subclasses even in other packages (unlike package-private). Use when shared hooks are meant for extension, but avoid exposing deep internals that break encapsulation across the whole hierarchy.


6. instanceof and safe narrowing

After if (obj instanceof AlarmClock ac) (pattern match Java 16+), ac is narrowed inside the block. Older style: cast after instanceof check. Prefer polymorphic designs that rarely need casts.


7. Design smell: deep trees

Very deep inheritance chains become hard to reason about. Favour composition (hold a helper object) when “is-a” feels forced; use inheritance when substitutability is genuinely required everywhere a superclass is accepted.

Examples

Example A — minimal hierarchy

public class Clock {
    private final String zone;

    public Clock(String zone) {
        this.zone = zone;
    }

    public String tickLabel() {
        return "tick@" + zone;
    }
}

public class AlarmClock extends Clock {
    private final int volume;

    public AlarmClock(String zone, int volume) {
        super(zone);
        this.volume = volume;
    }

    @Override
    public String tickLabel() {
        return super.tickLabel() + "(alarm vol=" + volume + ")";
    }
}

Calling tickLabel() on an AlarmClock reference executes the subclass body; storing it in a Clock variable still dispatches to AlarmClock at runtime.


Example B — overload vs override side by side

public class Ledger {
    public void record(String note) { /* ... */ }

    public void record(String note, int amount) { /* overload */ }
}

public class AuditedLedger extends Ledger {
    @Override
    public void record(String note) {
        super.record("[audit] " + note);
    }
    // record(String, int) inherited unless also overridden
}

The two-argument record is an overload in the superclass. The subclass overrides only the one-argument form.

Practice check — inheritance, super, and overriding

Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.

  1. 1.`extends` means…

  2. 2.What does `@Override` help with?

  3. 3.`super.method()` calls…

  4. 4.Substitution (intro level) means…

  5. 5.Overriding differs from overloading because overriding…