信息发布→ 登录 注册 退出

Java设计模式七大原则之里氏替换原则详解

发布时间:2026-01-11

点击量:
目录
  • 定义
  • 案例
    • 需求
    • 方案一
    • 方案二
  • 对比分析
    • 总结

      定义

      里氏替换原则(Liskov Substitution Principle,LSP),官方定义如下: 如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象 o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型,所有引用基类的地方必须能透明地使用其子类的对象。则通俗的来讲:子类可以扩展父类的功能,但是子类不能修改父类原有的功能 里氏替换原则就是给继承性的使用制定了规范

      案例

      需求

      现在有一个计算器(父类)可以完成加减乘除,定义其子类,来演示继承可能出现的问题

      方案一

      定义计算器类Calculator.java

      /**
       * 计算器类
       * @author:liyajie
       * @createTime:2025/1/31 15:25
       * @version:1.0
       */
      public class Calculator {
          //定义加法功能
          public int add(int a,int b){
              return a + b;
          }
          //定义减法功能
          public int sub(int a,int b){
              return a - b;
          }
      }

      定义超级计算器类SuperCalculator.java

      /**
       * 超级计算器类
       * @author:liyajie
       * @createTime:2025/1/31 15:25
       * @version:1.0
       */
      public class SuperCalculator extends Calculator{
          //增补需求,两数相加再加5
          @Override
          public int add(int a,int b){
              return a + b + 5;
          }
          //希望两数相加之和与100求差
          public int mul(int a,int b){
              int count = add(a, b);
              return 100 - count;
          }
      }

      定义测试类Test1.java

      /**
       * 测试类1
       * @author:liyajie
       * @createTime:2025/1/31 15:25
       * @version:1.0
       */
      public class Test1 {
      
          public static void main(String[] args) {
              int result = new Calculator().add(4,6);
              System.out.println("4和6之和为:" + result);
      
              int mul = new SuperCalculator().mul(4,6);
              System.out.println("4和6之和与100相差:" + mul);
          }
      }

      测试结果: 可以看到4和6之后与100相差的结果为85,明显是错误的答案。错误的原因就是SuperCalculator类继承Calculator类之后,重写了add方法,最终在调用的时候产生了错误的答案

      方案二

      定义基础类Base.java

      /**
       * 基础类
       * @author:liyajie
       * @createTime:2025/1/31 15:36
       * @version:1.0
       */
      public class Base {
          
      }

      改造后的超级计算器类SuperCalculatorNew.java

      /**
       * 超级计算器类
       * @author:liyajie
       * @createTime:2025/1/31 15:25
       * @version:1.0
       */
      public class SuperCalculatorNew extends Base{
      
          private Calculator calculator = new Calculator();
      
          //增补需求,两数相加再加5
          public int add(int a,int b){
              return a + b + 5;
          }
          //希望两数相加之和与100求差
          public int mul(int a,int b){
              int count = calculator.add(a, b);
              return (100 - count);
          }
      }

      测试类Test2.java

      /**
       * 测试类2
       * @author:liyajie
       * @createTime:2025/1/31 15:25
       * @version:1.0
       */
      public class Test2 {
      
          public static void main(String[] args) {
              int result = new Calculator().add(4,6);
              System.out.println("4和6之和为:" + result);
      
              int mul = new SuperCalculatorNew().mul(4,6);
              System.out.println("4和6之和与100相差:" + mul);
          }
      }

      测试结果: 可以看到测试结果正确

      对比分析

      方案一,直接继承计算器类,并重写了父类的非抽象方法add,导致在调用的时候产生了错误的结果 方案二,继承基础base类,并注入计算器类Calculator类作为依赖,遵守里氏替换原则,得出正确的结果

      总结

      1.子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法

      2.子类中可以扩展自己的方法

      3.里氏替换原则并非让我们尽量避免使用继承

      4.里氏替换原则是实现开闭原则的重要方式之一

      在线客服
      服务热线

      服务热线

      4008888355

      微信咨询
      二维码
      返回顶部
      ×二维码

      截屏,微信识别二维码

      打开微信

      微信号已复制,请打开微信添加咨询详情!