Liskov Substitution Principle

“objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program"



It means that we must make sure that new derived classes are extending the base classes without changing their behavior


Example:
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;
   }
}


Question: Square is a Rectangle?


Answer; Yes


"we must make sure that new derived classes are extending the base classes without changing their behavior"
if we say specifically  


"we must make sure that Square classes are extending the Rectangle without changing their behavior"


public class Square extends Rectangle {

   @Override
   public void setWidth(int width) {
       super.setWidth(width);
       super.setHeight(width);
   }

   @Override
   public void setHeight(int height) {
       super.setWidth(height);
       super.setHeight(height);
   }
}

Is the above sentence correct according to our program?


No, the problem is


without changing their behavior


but we change the behavior of the base Rectangle class


public class LiskovSubstitutionTest {

   public static void main(String args[]) {
       Rectangle rectangle = new Rectangle();
       rectangle.setWidth(2);
       rectangle.setHeight(5);

       if (rectangle.getArea() == 10) {
           System.out.println(rectangle.getArea());
       }
   }
}
Liskov Substitution Test  passed for Rectangle


public class LiskovSubstitutionTest {

   public static void main(String args[]) {
       Rectangle rectangle = new Square(); // Square
       rectangle.setWidth(2);
       rectangle.setHeight(5);

       if (rectangle.getArea() == 10) {
           System.out.println(rectangle.getArea());
       }
   }
}
Liskov Substitution Test  Failed  for Square.


Square is not a correct substitution for Rectangle since does not comply with the behavior of a Rectangle.
The Square / Rectangle hierarchy in isolation did not show any problems however, this violates the Liskov Substitution Principle!



Methods that use references to the base classes must be able to use the objects of the derived classes without knowing it


If the subtype is not replaceable for the supertype reference, then in order to support the subtype instances as well we go ahead and make changes to the existing code and add the support. This is a clear violation of OCP.


Solotion:-
public interface Shape {
   int area();
}


public class Rectangle implements Shape {

   private int width;
   private int height;

   public void setWidth(int width) {
       this.width = width;
   }

   public void setHeight(int height) {
       this.height = height;
   }

   @Override
   public int area() {
       return width * height;
   }
}

public class Square implements Shape {

   private int size;

   public void setSize(int size) {
       this.size = size;
   }

   @Override
   public int area() {
       return size * size;
   }
}

Comments