里氏替换原则

92 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情

基本介绍

  1. 里氏替换原则(Liskov Substitution Principle)在,1988 年,由麻省理工学院的一位姓里的女士提出。
  2. 所有使用父类对象的地方,都应该可以透明的替换为子类的对象。
  3. 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
  4. 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题。
  5. 关于重写
  • 重写的方法不能比被重写的方法抛出更宽泛的异常

  • 重写的方法不能比被重写的方法有更严格的修饰符

  • 为什么要有这两个限制:

    • 保证子类对象替换父类对象之后,语法不会报错。 符合里氏替换原则。
  1. 判断两个类是否可以继承

    • 是否存在 is a 关系
    • 是否可以实现子类透明的替换父类

代码举例

反例

  • 代码

     ​
     //长方形
     class Rectangle{
         private double length;
         private double width;
     ​
         public double getLength() {
             return length;
         }
     ​
         public void setLength(double length) {
             this.length = length;
         }
     ​
         public double getWidth() {
             return width;
         }
     ​
         public void setWidth(double width) {
             this.width = width;
         }
     ​
         @Override
         public String toString() {
             return "Rectangle{" + "length=" + length + ", width=" + width + '}';
         }
     }
     ​
     // 正方形
     class Square extends Rectangle{
         // 边长
         private double sidLength;
     ​
         @Override
         public double getLength() {
             return sidLength;
         }
     ​
         @Override
         public void setLength(double length) {
             this.sidLength = length;
         }
     ​
         @Override
         public double getWidth() {
             return sidLength;
         }
     ​
         @Override
         public void setWidth(double width) {
             this.sidLength = width;
         }
     ​
         @Override
         public String toString() {
             return "sidLength = " + this.sidLength;
         }
     }
     ​
     class Utils{
         //变形 让宽等与长
         public static void transform(Rectangle rectangle){
             while (rectangle.getWidth() < rectangle.getLength()){
                 rectangle.setWidth(rectangle.getWidth()+1);
                 System.out.println("rectangle.width = " + rectangle.getWidth());
             }
         }
     }
     ​
     public class negtive.AppTest {
     ​
         public static void main(String[] args) {
     ​
             //创造长方形
             Rectangle rectangle = new Rectangle();
             rectangle.setWidth(10);
             rectangle.setLength(20);
             System.out.println(rectangle);
             //变形
             Utils.transform(rectangle);
             System.out.println(rectangle);
             //创造正方形
             Square square = new Square();
             square.setWidth(10);
             square.setLength(20);
             System.out.println(square);
             //变形
             Utils.transform(square); //死循环
             System.out.println(square);
         }
     }
    
  • 分析

    • 在用正方形替换长方形父类之后,发现程序的逻辑变为死循环。不符合里氏替换原则。

正例

  • 代码

     //长方形
     class Rectangle{
         private double length;
         private double width;
     ​
         public double getLength() {
             return length;
         }
     ​
         public void setLength(double length) {
             this.length = length;
         }
     ​
         public double getWidth() {
             return width;
         }
     ​
         public void setWidth(double width) {
             this.width = width;
         }
     ​
         @Override
         public String toString() {
             return "Rectangle{" + "length=" + length + ", width=" + width + '}';
         }
     }
     ​
     // 正方形
     class Square{
         // 边长
         private double sidLength;
     ​
         public double getSidLength() {
             return sidLength;
         }
     ​
         public void setSidLength(double sidLength) {
             this.sidLength = sidLength;
         }
     }
     ​
     class Utils{
         //变形 让宽等与长
         public static void transform(Rectangle rectangle){
             while (rectangle.getWidth() <= rectangle.getLength()){
                 rectangle.setWidth(rectangle.getWidth()+1);
                 System.out.println("rectangle.width = " + rectangle.getWidth());
             }
         }
     }
     ​
     public class negtive.AppTest {
     ​
         public static void main(String[] args) {
     ​
             //创造长方形
             Rectangle rectangle = new Rectangle();
             rectangle.setWidth(10);
             rectangle.setLength(20);
     ​
             System.out.println(rectangle);
     ​
             //变形
             Utils.transform(rectangle);
     ​
             System.out.println(rectangle);
             
         }
     ​
     }
    
  • 分析

    断绝继承关系