🧩 OOP Concepts Intermediate

What is the Liskov Substitution Principle?

Answer

The Liskov Substitution Principle (LSP) states: If class B is a subclass of A, then objects of type B should be substitutable for objects of type A without altering the correctness of the program. Subclasses must honor the behavioral contract of the base class. Classic LSP violation — Square extends Rectangle: class Rectangle { protected double width, height; public void setWidth(double w) { this.width = w; } public void setHeight(double h) { this.height = h; } public double area() { return width * height; } } class Square extends Rectangle { @Override public void setWidth(double w) { this.width = w; this.height = w; // Square must keep equal sides! } @Override public void setHeight(double h) { this.width = h; this.height = h; } } // LSP test: void testArea(Rectangle r) { r.setWidth(5); r.setHeight(4); assert r.area() == 20 : "Area should be 20"; // Fails for Square! (25, not 20) } Rectangle rect = new Square(); testArea(rect); // Breaks! Square violates Rectangle's contract. Fix — separate hierarchy: interface Shape { double area(); } class Rectangle implements Shape { /* ... */ } class Square implements Shape { /* ... */ } // Neither extends the other -- no LSP violation possible. LSP rules for subclasses: don't strengthen preconditions (don't require more than base); don't weaken postconditions (don't provide less than base); preserve invariants of base class; don't throw new checked exceptions not in base interface; override methods must have same or weaker preconditions, same or stronger postconditions. LSP enables: true substitutability, reliable polymorphism, correct inheritance hierarchies. Ask: "Is Square really a Rectangle in behavior?" — if no, don't inherit.