前言
里氏替换原则简单的理解可以是父类用到的地方可以用子类替换并且不改变逻辑,这就要求子类可以扩展父类的功能,但不能改变父类原有的功能。里氏替换原则要求
(1) 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法,
(2) 子类可以增加自己特有的方法
(3) 当子类的方法重载父类的方法时,方法的入参要比父类方法的入参更宽松,但返回值要比父类更严格
接下来我们就用一个案例来解释
案例
在生活中,有矩形和正方形,正方形是长宽相等的矩形,所以我们新建这样两个类
public class Rectanger {
private long height;
private long width;
public long getHeight() {
return height;
}
public void setHeight(long height) {
this.height = height;
}
public long getWidth() {
return width;
}
public void setWidth(long width) {
this.width = width;
}
}
public class Square extends Rectanger{
private long length;
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public long getHeight() {
return getLength();
}
public void setHeight(long height) {
setLength(length);
}
public long getWidth() {
return getLength();
}
public void setWidth(long width) {
setLength(length);
}
}
在Test里新建方法,当长方体的宽大于等于高的时候,我们让高一直自增,直到高等于宽
public static void resize(Rectanger rectangle) {
while(rectangle.getWidth() >= rectangle.getHeight()) {
rectangle.setHeight(rectangle.getHeight()+1);
System.out.println("width:"+rectangle.getWidth()+",height:"+rectangle.getHeight());
}
System.out.println("resize方法结束");
}
然后在main方法中我们用长方体来测试
public static void main(String[] args) {
Rectanger rectanger = new Rectanger();
rectanger.setWidth(20);
rectanger.setHeight(10);
resize(rectanger);
}
运行结果如下:
然后我们用正方形来测试
public static void main(String[] args) {
/*Rectanger rectanger = new Rectanger();
rectanger.setWidth(20);
rectanger.setHeight(10);
resize(rectanger);*/
Square square = new Square();
square.setLength(10);
resize(square);
}
我们测试的时候发现代码是无限循环
为什么会出现这种情况呢,这就是因为此处不复合里氏替换原则,子类Square重写了Rectangle的相应方法,改变了相应的逻辑规则
改造
接下来我们创建一个基于长方形和正方形的抽象四边接口Quadrangle
public interface Quadrangle {
long getWidth();
long getHeight();
}
然后改造Rectangle和Square实现Quadrangle接口
public class Rectanger implements Quadrangle{
private long height;
private long width;
public long getHeight() {
return height;
}
public void setHeight(long height) {
this.height = height;
}
public long getWidth() {
return width;
}
public void setWidth(long width) {
this.width = width;
}
}
public class Square implements Quadrangle{
private long length;
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public long getHeight() {
return getLength();
}
public long getWidth() {
return getLength();
}
}
此时Square 没有setHeight和setWidth方法
所以在测试的时候如果Square参与resize方法会在编译的时候就报错