Liskov Substitution Principle
LSP
“Subtypes must be substitutable for their base types without altering the correctness of the program.” – Barbara Liskov
If $S$ is a subtype of $T$, then objects of type $T$ may be replaced with objects of type $S$ without altering any of the desirable properties of the program (correctness, task performed, etc.).
When to use
When designing class hierarchies. Ensure that derived classes extend the base class without changing the behavior that clients expect.
Why it matters
- Reliability: Clients can trust that subclasses won’t blow up or behave wildly differently.
- Polymorphism: Real polymorphism relies on LSP. If you have to check
if (obj instanceof Subclass)to avoid errors, you violated LSP.
Signs of Violation
- A subclass throws a
NotImplementedExceptionfor a method defined in the parent. - A subclass overrides a method but does nothing (empty body).
- A subclass tightens the preconditions (accepts fewer inputs) or loosens postconditions (returns wider outputs) than the parent.
Explanation
Problem
If a subclass masquerades as a parent class but fails to perform the same duties, code that uses the parent class will fail when handed the subclass.
Solution
Design inheritance hierarchies such that subclasses strictly adhere to the contract defined by the parent. If a subclass cannot perform a behavior, maybe it shouldn’t inherit from that parent.
Real world analogy
If you look like a duck and quack like a duck, but you need batteries, you are a wrong abstraction. If a father promises to pay the bill, the son (subtype) should also be able to pay the bill (or at least not refuse to).
Pros and Cons
| Pros | Cons |
|---|---|
Comparison
- Design by Contract: LSP is a specific application of Design by Contract logic to inheritance.
Code example
Typescript
Bad (Violation)
Good (Adherence)
PHP
Bad (Violation)
Good (Adherence)