Liskov Substitution Principle (LSP)
HardIn plain terms
The Liskov Substitution Principle says that if class S is a subtype of T, then you should be able to replace T with S without breaking the program. Callers that depend on T should not need to know whether they have a T or an S.
Violations often come from overrides that change behavior in unexpected ways (e.g. a "Square" that does not behave like a "Rectangle" when you set width and height). To satisfy LSP, subclasses must honor the contract of the base class: same expectations for inputs and outputs, and no stronger preconditions or weaker postconditions. Design your hierarchies so subtypes are true substitutes.
What you need to know
- •Subtype substitutable for base type
- •Honor the contract
- •No surprising overrides
Example
Code is language-agnostic in spirit; adapt the idea to your language:
// If Bird has fly(), Penguin might not be a valid Bird
// LSP: subtypes must not break base type contract
class Shape {
area() { throw new Error("Override"); }
}
class Rectangle extends Shape {
area() { return this.w * this.h; }
}
// Square extends Rectangle: must still behave like RectangleWhy this matters
LSP is the least obvious SOLID principle but is asked in senior interviews. Violations (e.g. Square/Rectangle) are classic examples.
How it connects
Inheritance and polymorphism only work if subtypes honor the base contract. Breaking LSP breaks OCP for callers who depend on the base type. Design hierarchies so subclasses are true substitutes.
Interview focus
Be ready to explain these; they come up often.
- ▸Subtypes must be substitutable for their base type without breaking callers.
- ▸Classic violation: Square extending Rectangle but changing setWidth/setHeight behavior.
- ▸Rule: same preconditions/postconditions; do not strengthen preconditions or weaken postconditions.
Learn more
Dive deeper with these resources: