What is the Liskov Substitution Principle?

SOLID & Design Patterns SOLID Advanced 3–5 Yrs5+ Yrs Architecture 1 min read

Quick Answer

LSP says a subtype must be usable anywhere its base type is expected, without the caller noticing. A subclass can't strengthen preconditions, weaken postconditions, throw new exceptions the base doesn't, or violate the base's invariants. If substituting the subclass breaks code that works with the base, the hierarchy is wrong.

Liskov substitution means if I have code written against a base class, I should be able to hand it any subclass and it just works — no surprises. A subclass can't tighten what inputs it accepts, loosen its guarantees, or throw exceptions the base never would. The famous example is a Square inheriting from Rectangle: code that sets width and height separately and checks them breaks when a square forces them equal. The other tell is overriding a method just to throw “not supported” — that's a sign the class doesn't really fit the hierarchy.

  • Square/Rectangle: Square : Rectangle — code that sets width and height independently and asserts both breaks for a square that forces them equal. They shouldn't be in an inheritance relationship.
  • Smell: overriding a method to throw new NotSupportedException() (e.g. a read-only collection deriving from a mutable one).
  • Fix: split the interface (ISP), use composition, or model the concepts separately.