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

 更新时间:2022年02月09日 09:20:26   作者:温故知新之java  
在面向对象的程序设计中,里氏替换原则(Liskov Substitution principle)是对子类型的特别定义。本文将为大家详细介绍Java设计模式七大原则之一的里氏替换原则,需要的可以参考一下

定义

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

案例

需求

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

方案一

定义计算器类Calculator.java

/**
 * 计算器类
 * @author:liyajie
 * @createTime:2022/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:2022/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:2022/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:2022/1/31 15:36
 * @version:1.0
 */
public class Base {
    
}

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

/**
 * 超级计算器类
 * @author:liyajie
 * @createTime:2022/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:2022/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.里氏替换原则是实现开闭原则的重要方式之一

到此这篇关于Java设计模式七大原则之里氏替换原则详解的文章就介绍到这了,更多相关Java里氏替换原则内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中String、StringBuffer和StringBuilder的区别与使用场景

    Java中String、StringBuffer和StringBuilder的区别与使用场景

    在Java编程中,String、StringBuffer和StringBuilder是用于处理字符串的常见类,它们在可变性、线程安全性和性能方面有所不同,具有一定的参考价值,感兴趣的可以了解一下
    2024-05-05
  • SpringMVC中@ModelAttribute与@RequestBody的区别及说明

    SpringMVC中@ModelAttribute与@RequestBody的区别及说明

    这篇文章主要介绍了SpringMVC中@ModelAttribute与@RequestBody的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 从java中调用matlab详细介绍

    从java中调用matlab详细介绍

    这篇文章主要介绍了从java中调用matlab,有需要的朋友可以参考一下
    2013-12-12
  • spring依赖注入知识点分享

    spring依赖注入知识点分享

    在本篇文章里小编给大家整理的是关于spring依赖注入知识点以及相关代码内容,需要的朋友们学习下。
    2019-11-11
  • springboot + mybatis-plus实现多表联合查询功能(注解方式)

    springboot + mybatis-plus实现多表联合查询功能(注解方式)

    这篇文章主要介绍了springboot + mybatis-plus实现多表联合查询功能,是最简单的一种注解方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • 在spring中手写全局异常拦截器

    在spring中手写全局异常拦截器

    这篇文章主要介绍了如何在spring中手写全局异常拦截器,帮助大家更好的理解和使用spring框架,感兴趣的朋友可以了解下
    2020-11-11
  • idea中的Maven导包失败问题解决方案汇总

    idea中的Maven导包失败问题解决方案汇总

    这篇文章主要介绍了idea中的Maven导包失败问题解决总结,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • Java中LinkedHashSet的底层机制详解

    Java中LinkedHashSet的底层机制详解

    这篇文章主要介绍了Java中LinkedHashSet的底层机制解读,   LinkedHashSet是具有可预知迭代顺序的Set接口的哈希表和链接列表实现,此实现与HashSet的不同之处在于,后者维护着一个运行于所有条目的双重链接列表,需要的朋友可以参考下
    2023-09-09
  • Java通过反射获取方法参数名的方式小结

    Java通过反射获取方法参数名的方式小结

    这篇文章主要为大家详细介绍了Java如何通过反射获取方法参数名的方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-02-02
  • Java Web项目中如何添加Tomcat的Servlet-api.jar包(基于IDEA)

    Java Web项目中如何添加Tomcat的Servlet-api.jar包(基于IDEA)

    servlet-api.jar是在编写servlet必须用到的jar包下面这篇文章主要给大家介绍了基于IDEAJava Web项目中如何添加Tomcat的Servlet-api.jar包的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-04-04

最新评论