Liskov substitution principle (LSP) is one of the five SOLID principles, which gives us a way to characterize good inheritance. It states that a superclass object should be replaceable with a subclass object without breaking the software’s functionality.
If you have a base class and a class inheriting from that base class, then the subclass should be substitutable for the base class at any point in the program. So in every place where you are using the base type, you should be able to swap that instance with an instance of the subtype without causing any unwanted behavior in the program.
You are breaking the Liskov substitution principle as soon as you are inheriting from the base class in a way that makes the subclass not substitutable for this particular base class.
Violations of a Liskov substitution principle indicate that your system may be poorly architectured in terms of inheritance, and you may be overusing inheritance in a place where inheritance shouldn’t be used.
This principle is just an extension of the open-closed principle, and we must ensure that new derived classes are extending the base classes without changing their behavior.
Liskov substitution principle Example
Consider the below example to better understand the Liskov substitute principle (LSP)
- Assume we have a rectangle
- A square is mathematically a rectangle, so we decide to implement a square as a subclass of a rectangle.
- As shown below diagram, we will override the setHeight and setWidth methods to ensure that square instances always remain mathematically valid. We reuse the rest of the methods of the ‘Rectangle’ class (setWidth)

The following code illustrates the simple class which implements the Rectangle class
public class Rectangle { private int width; private int height; public void setWidth(int width) { this.width = width; } public void setHeight(int height) { this.height = height; } public int getArea( ) { return width * height; } }
As explained, since a square is mathematically a rectangle, let us implement the class Square as a subclass of a Rectangle. We will override the setHeight and setWidth methods to ensure that square instances remain mathematically valid. We reuse the method getArea of the ‘Rectangle’ class
class Square extends Rectangle { public void setWidth(int width) { /* we are overriding and changing the base class behavior in this setWidth method */ this.width = width; this.height = width; } public void setHeight(int height) { /* we are overriding and changing the base class behavior in this setHeight method */ this.width = height; this.height = height; } }
In the above code snippet
- A square does not need both height and width fields; it inherits them anyway
- As the methods setHeight and setWidth are inappropriate for Square, we will override the setHeight and setWidth methods.
With this overriding of setHeight and setWidth, to set both dimensions to the same value, instances of class Square remain mathematically valid Square.
However, making Square a subtype of Rectangle violates the Liskov substitution principle.
class clientClass { private static Rectangle getNewRectangle () { /*subtyping rules tell us that we can pass Square everywhere a Rectangle is expected. But what happens if we pass Square to some client methods?*/ return new Square(); } private static Rectangle getBaseRectangle () { /*We are directly returning the base class Reactangle to client methods*/ return new Rectangle(); } public static void main(String args[]) { /* Here, We know that r is a rectangle so we can set width and height as per the base class */ Rectangle r = clientClass.getNewRectangle(); r.setWidth(5); r.setHeight(10); /*but below printf statement prints the area as 100 instead of 50 */ System.out.println(r.getArea()); /*here, rBase is a rectangle */ Rectangle r1 = clientClass.getBaseRectangle(); r1.setWidth(5); r1.setHeight(10); /*Below printf statement prints the correct area of rectange i.e 50*/ System.out.println(r1.getArea()); } }
- In line #8, we are passing an object of Square instead of the object of Rectangle; as we know, the inheritance rule says that we can pass Squareeverywhere Rectangle is expected.
- However, in line #15, we are passing an object of Rectangle (base class). so it is one on one mapping
- println statement in line #27 prints the area as 100 instead of 50. so, clientClass breaks when we pass Square object (Inherited from Rectangle)
- println statement in line #35 does not break as we are passing the base class object (Object of type Rectangle)
- clientClass works fine with Rectangle, but it breaks when Square is passed.
- The Rectangle and Square hierarchy in the above code violates the Liskov substitution principle.
The solution to this problem is to make two separate classes: Rectangle and Square,instead of inheriting Square from Square.
