Java設(shè)計(jì)模式七大原則之里氏替換原則詳解
定義
里氏替換原則(Liskov Substitution Principle,LSP),官方定義如下: 如果對每一個類型為S的對象o1,都有類型為T的對象o2,使得以T定義的所有程序P在所有的對象 o1都代換成o2時,程序P的行為沒有發(fā)生變化,那么類型S是類型T的子類型,所有引用基類的地方必須能透明地使用其子類的對象。則通俗的來講:子類可以擴(kuò)展父類的功能,但是子類不能修改父類原有的功能 里氏替換原則就是給繼承性的使用制定了規(guī)范
案例
需求
現(xiàn)在有一個計(jì)算器(父類)可以完成加減乘除,定義其子類,來演示繼承可能出現(xiàn)的問題
方案一
定義計(jì)算器類Calculator.java
/**
* 計(jì)算器類
* @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;
}
}定義超級計(jì)算器類SuperCalculator.java
/**
* 超級計(jì)算器類
* @author:liyajie
* @createTime:2022/1/31 15:25
* @version:1.0
*/
public class SuperCalculator extends Calculator{
//增補(bǔ)需求,兩數(shù)相加再加5
@Override
public int add(int a,int b){
return a + b + 5;
}
//希望兩數(shù)相加之和與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);
}
}測試結(jié)果: 可以看到4和6之后與100相差的結(jié)果為85,明顯是錯誤的答案。錯誤的原因就是SuperCalculator類繼承Calculator類之后,重寫了add方法,最終在調(diào)用的時候產(chǎn)生了錯誤的答案

方案二
定義基礎(chǔ)類Base.java
/**
* 基礎(chǔ)類
* @author:liyajie
* @createTime:2022/1/31 15:36
* @version:1.0
*/
public class Base {
}改造后的超級計(jì)算器類SuperCalculatorNew.java
/**
* 超級計(jì)算器類
* @author:liyajie
* @createTime:2022/1/31 15:25
* @version:1.0
*/
public class SuperCalculatorNew extends Base{
private Calculator calculator = new Calculator();
//增補(bǔ)需求,兩數(shù)相加再加5
public int add(int a,int b){
return a + b + 5;
}
//希望兩數(shù)相加之和與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);
}
}測試結(jié)果: 可以看到測試結(jié)果正確

對比分析
方案一,直接繼承計(jì)算器類,并重寫了父類的非抽象方法add,導(dǎo)致在調(diào)用的時候產(chǎn)生了錯誤的結(jié)果 方案二,繼承基礎(chǔ)base類,并注入計(jì)算器類Calculator類作為依賴,遵守里氏替換原則,得出正確的結(jié)果
總結(jié)
1.子類可以實(shí)現(xiàn)父類的抽象方法,但是不能覆蓋父類的非抽象方法
2.子類中可以擴(kuò)展自己的方法
3.里氏替換原則并非讓我們盡量避免使用繼承
4.里氏替換原則是實(shí)現(xiàn)開閉原則的重要方式之一
到此這篇關(guān)于Java設(shè)計(jì)模式七大原則之里氏替換原則詳解的文章就介紹到這了,更多相關(guān)Java里氏替換原則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中String、StringBuffer和StringBuilder的區(qū)別與使用場景
在Java編程中,String、StringBuffer和StringBuilder是用于處理字符串的常見類,它們在可變性、線程安全性和性能方面有所不同,具有一定的參考價值,感興趣的可以了解一下2024-05-05
SpringMVC中@ModelAttribute與@RequestBody的區(qū)別及說明
這篇文章主要介紹了SpringMVC中@ModelAttribute與@RequestBody的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11
springboot + mybatis-plus實(shí)現(xiàn)多表聯(lián)合查詢功能(注解方式)
這篇文章主要介紹了springboot + mybatis-plus實(shí)現(xiàn)多表聯(lián)合查詢功能,是最簡單的一種注解方式,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
Java通過反射獲取方法參數(shù)名的方式小結(jié)
這篇文章主要為大家詳細(xì)介紹了Java如何通過反射獲取方法參數(shù)名的方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02
Java?Web項(xiàng)目中如何添加Tomcat的Servlet-api.jar包(基于IDEA)
servlet-api.jar是在編寫servlet必須用到的jar包下面這篇文章主要給大家介紹了基于IDEAJava?Web項(xiàng)目中如何添加Tomcat的Servlet-api.jar包的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04

