Card 09/ 09

RecapDifficulty: Intermediate1 min

Recap: Liskov Substitution

A subtype must work wherever its parent does, and a type check in the caller says it does not.

The Liskov substitution principle keeps inheritance safe for the code that uses it.

  • A subtype must work anywhere its parent is expected. Matching method names is not enough; the behaviour must match what callers rely on.
  • The failure appears in the caller, in code that was correct, which is why it is hard to trace.
  • Three rules make it checkable: do not strengthen preconditions, do not weaken postconditions, preserve invariants. Ask for no more, promise no less.
  • Fix the abstraction, not the subclass. If some children cannot keep a promise, move the promise to a narrower parent, as fly moved to FlyingBird.
  • Real-world "is a" does not decide inheritance. A square is a rectangle in geometry but not in mutable code.
  • Libraries make trade-offs. Java's List.add is an optional operation, so List.of can throw from it.
  • A type check in the caller is a symptom. It means a subtype already broke its parent's promise.