Unit 12 · lesson

Inheritance Makes an Is-a Claim

Consider a broad type:

class Notification {
    String message;

    Notification(String message) {
        this.message = message;
    }

    String format() {
        return message;
    }
}

A subtype:

class UrgentNotification extends Notification {
    UrgentNotification(String message) {
        super(message);
    }

    @Override
    String format() {
        return "URGENT: " + message;
    }
}
Concept flow

Inheritance makes a substitutability claim

A subtype must preserve meaningful expectations of the broader type.

  1. SUPERCLASSdefines broader state and behavior
    extended by
  2. SUBTYPEclaims to be a valid specialized form
    override
  3. BEHAVIORspecialized implementation may change an operation
    used as
  4. BROADER TYPEcaller should not need unsafe subtype assumptions
    verify
  5. IS-A EVIDENCEtests and reasoning defend substitutability

The design claims:

UrgentNotification is a Notification

That means code expecting the broader type should be able to use the subtype without the relationship becoming nonsensical.

extends provides more than reuse

The subtype inherits accessible behavior/state and participates in a type relationship.

That type relationship is the bigger commitment.

If your only reason is "I want this helper method," inheritance may be too strong. A composed helper or extracted function can reuse behavior without claiming an is-a relationship.

Protected and public are design decisions

Subclasses need access to some superclass behavior, but exposing fields broadly can weaken invariants.

Do not respond to every access problem by changing fields to protected or public.

Prefer superclass methods that preserve the superclass contract when possible.

Constructor chaining

super(...) initializes the superclass portion of the object.

The subtype does not bypass the need for a valid parent state.

If a parent constructor enforces an invariant, the subtype should not create a back door around it.

Overriding changes behavior under the same operation

@Override asks the compiler to verify that a superclass/interface method is actually being overridden.

Use it. A spelling mistake without @Override can accidentally create a new method instead of replacing the intended behavior.

Test the is-a sentence

For each pair, decide whether inheritance is plausible, composition is better, or more information is needed:

  • ElectricCar and Car;
  • Robot and Motor;
  • CsvFormatter and Formatter;
  • Student and Address;
  • Square and Rectangle when width/height mutation rules exist.

Do not decide only from English nouns. Ask whether the subtype can preserve the parent's behavioral expectations.

Evidence

Create one small superclass/subclass relationship. Write the is-a sentence and at least two operations that a caller can safely use through the broader type.

Then name one class from your earlier composition work that should not become a superclass and explain why the relationship would be false or unnecessarily tight.