Why does Square extending Rectangle violate the Liskov Substitution Principle?
A Square must keep width and height equal, so setting one changes the other. Code written for any Rectangle, expecting independent sides, gets wrong results when given a Square.
Explain it simply
In geometry a square is a rectangle, but in code the question is whether a Square object behaves the way a Rectangle object promises. Rectangle promises "set width, set height, and they do not affect each other". Square cannot keep that promise.
Example
class Rectangle {
protected int w, h;
void setW(int w) { this.w = w; }
void setH(int h) { this.h = h; }
int area() { return w * h; }
}
class Square extends Rectangle {
@Override void setW(int w) { this.w = w; this.h = w; }
@Override void setH(int h) { this.w = h; this.h = h; }
}
static int test(Rectangle r) {
r.setW(5);
r.setH(4);
return r.area(); // caller expects 20
}
test(new Rectangle()); // 20
test(new Square()); // 16, the subclass broke the caller's expectationA fix is to make both implement a Shape interface with area(), or to make them immutable so there are no setters to conflict.
What to say in the interview
"LSP says a subclass must work wherever its parent is expected without surprising the caller. Square changes both sides when one is set, so code that treats it as a Rectangle gets 16 instead of 20. The inheritance is valid in maths but wrong in behaviour."
Common mistakes
- Deciding inheritance by real-world is-a rather than by behaviour.