“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;
}
}
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);
}
}
@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());
}
}
}
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());
}
}
}
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();
}
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;
}
}
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;
}
}
private int size;
public void setSize(int size) {
this.size = size;
}
@Override
public int area() {
return size * size;
}
}
Comments