设计原则:里氏替换原则

定义:如果对于每一个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义的所有程序P在所有的对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。
定义扩展:一个软件实体如果适用一个父类的话,那一定适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。
引申意义:子类可以扩展父类的功能,但不能改变父类原有的功能。
含义1:子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
含义2:子类可以增加自己特有的方法。
含义3:当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类的输入参数更宽松。
含义4:当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或相等。
优点1:约束继承泛滥,开闭原则的一种体现
优点2:加强程序的健壮性,同时变更时也可以做到非常好的兼容性,提高程序的维护性、扩展性。降低需求变更时引入的风险。

示例

长方形与正方形(1)

代码实现

  1. 创建Rectangle类
import lombok.Data;

/**
 * @author lijiayin
 */
@Data
public class Rectangle {
    
    private Long width;
    
    private Long length;
}
  1. 创建Square类
import lombok.Data;

/**
 * @author lijiayin
 */
@Data
public class Square extends Rectangle {
    
    private Long sideLength;

    @Override
    public Long getWidth() {
        return sideLength;
    }

    @Override
    public Long getLength() {
        return sideLength;
    }

    @Override
    public void setWidth(Long width) {
        this.sideLength = width;
    }

    @Override
    public void setLength(Long length) {
        this.sideLength = length;
    }
}
  1. 测试Rectangle类
/**
 * @author lijiayin
 */
public class Test {
    
    public static void resize(Rectangle rectangle){
        while (rectangle.getLength() <= rectangle.getWidth()){
            rectangle.setLength(rectangle.getLength() + 1);
            System.out.println("width:" + rectangle.getWidth() + ", length:" + rectangle.getLength());
        }
        System.out.println("完成resize,width:" + rectangle.getWidth() + ", length:" + rectangle.getLength());
    }

    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle();
        rectangle.setLength(9L);
        rectangle.setWidth(10L);
        resize(rectangle);
    }
}
  1. 测试结果


    测试结果.png
  2. 测试Square类
/**
 * @author lijiayin
 */
public class Test {
    
    public static void resize(Rectangle rectangle){
        while (rectangle.getLength() <= rectangle.getWidth()){
            rectangle.setLength(rectangle.getLength() + 1);
            System.out.println("width:" + rectangle.getWidth() + ", length:" + rectangle.getLength());
        }
        System.out.println("完成resize,width:" + rectangle.getWidth() + ", length:" + rectangle.getLength());
    }

    public static void main(String[] args) {
        Square square = new Square();
        square.setSideLength(10L);
        resize(square);
    }
}
  1. 测试结果


    测试结果

    进入无限循环中,不能替换父类Rectangle,破坏了里氏替换原则

长方形与正方形(2)

代码实现

  1. 创建Quadrangle接口,只有get方法
/**
 * @author lijiayin
 */
public interface Quadrangle {
    Long getWidth();
    Long getLength();
}
  1. 修改Rectangle类
import lombok.Data;

/**
 * @author lijiayin
 */
@Data
public class Rectangle implements Quadrangle{
    
    private Long width;
    
    private Long length;
}
  1. 修改Square类
import lombok.Data;

/**
 * @author lijiayin
 */
@Data
public class Square implements Quadrangle {
    
    private Long sideLength;

    @Override
    public Long getWidth() {
        return sideLength;
    }

    @Override
    public Long getLength() {
        return sideLength;
    }
}
  1. 修改测试类


    测试类.png

    由于没有set方法,因此编译不通过,约束了继承泛滥,满足了里氏替换原则,该方法只能用于Rectangle类。

你可能感兴趣的:(设计原则:里氏替换原则)