Unit 12 · lesson

Prefer the Relationship You Can Defend

Composition and inheritance can sometimes solve the same immediate coding problem. Their long-term claims are different.

Inheritance:

A is a B
A inherits/overrides B behavior
A must remain substitutable for B's contract

Composition:

A has a B/capability
A delegates some responsibility
collaborator can often be replaced independently

Example: powered device

Bad instinct:

Robot extends Battery

A robot uses a battery. It is not a battery.

Composition expresses the domain:

class Robot {
    private final PowerSource power;
}

Example: notification specialization

If UrgentNotification genuinely preserves every Notification expectation and only specializes formatting/priority behavior, inheritance may be reasonable.

But if urgent notices have an entirely different lifecycle and incompatible operations, a separate implementation of a Notification interface may be cleaner than subclassing a concrete parent.

Reuse is not enough evidence

Suppose two classes both need:

String sanitize(String text)

That does not prove one class should extend the other. Shared behavior can live in a focused collaborator or utility when no subtype relationship exists.

Do not create a dishonest hierarchy to save ten lines.

Change direction matters

Inheritance couples a subclass to details and contracts of its superclass. Changes in parent behavior can affect all descendants.

Composition couples a class to a collaborator contract. A new implementation can often be introduced without modifying the coordinator.

Neither is free. The design question is which dependency reflects the domain and expected change pattern.

Design review

Take this fictional system:

EmailAlert
ConsoleAlert
UrgentEmailAlert
AlertFormatter
DeliveryChannel

Create two possible architectures:

  1. an inheritance-heavy tree;
  2. an interface + composition design.

Evaluate each by:

  • substitutability;
  • responsibility clarity;
  • change impact;
  • testability;
  • whether the is-a sentences remain true.

You may choose a hybrid if you can defend it.

Rejected inheritance evidence

A strong software designer can explain why they did not use inheritance.

Choose one pair of classes where shared code makes inheritance tempting but the domain relationship is weak.

Write:

Tempting hierarchy:
Why it compiles:
Why the is-a claim is weak/false:
Composition or other alternative:
Tradeoff accepted:

Evidence

Submit one inheritance decision and one composition decision from the same small system. The rubric rewards the reasoning, not the number of extends keywords.