詳解Java設(shè)計(jì)模式編程中的里氏替換原則
定義1:如果對(duì)每一個(gè)類(lèi)型為 T1的對(duì)象 o1,都有類(lèi)型為 T2 的對(duì)象o2,使得以 T1定義的所有程序 P 在所有的對(duì)象 o1 都代換成 o2 時(shí),程序 P 的行為沒(méi)有發(fā)生變化,那么類(lèi)型 T2 是類(lèi)型 T1 的子類(lèi)型。
定義2:所有引用基類(lèi)的地方必須能透明地使用其子類(lèi)的對(duì)象。
問(wèn)題由來(lái):有一功能P1,由類(lèi)A完成?,F(xiàn)需要將功能P1進(jìn)行擴(kuò)展,擴(kuò)展后的功能為P,其中P由原有功能P1與新功能P2組成。新功能P由類(lèi)A的子類(lèi)B來(lái)完成,則子類(lèi)B在完成新功能P2的同時(shí),有可能會(huì)導(dǎo)致原有功能P1發(fā)生故障。
解決方案:當(dāng)使用繼承時(shí),遵循里氏替換原則。類(lèi)B繼承類(lèi)A時(shí),除添加新的方法完成新增功能P2外,盡量不要重寫(xiě)父類(lèi)A的方法,也盡量不要重載父類(lèi)A的方法。
繼承包含這樣一層含義:父類(lèi)中凡是已經(jīng)實(shí)現(xiàn)好的方法(相對(duì)于抽象方法而言),實(shí)際上是在設(shè)定一系列的規(guī)范和契約,雖然它不強(qiáng)制要求所有的子類(lèi)必須遵從這些契約,但是如果子類(lèi)對(duì)這些非抽象方法任意修改,就會(huì)對(duì)整個(gè)繼承體系造成破壞。而里氏替換原則就是表達(dá)了這一層含義。
繼承作為面向?qū)ο笕筇匦灾?,在給程序設(shè)計(jì)帶來(lái)巨大便利的同時(shí),也帶來(lái)了弊端。比如使用繼承會(huì)給程序帶來(lái)侵入性,程序的可移植性降低,增加了對(duì)象間的耦合性,如果一個(gè)類(lèi)被其他的類(lèi)所繼承,則當(dāng)這個(gè)類(lèi)需要修改時(shí),必須考慮到所有的子類(lèi),并且父類(lèi)修改后,所有涉及到子類(lèi)的功能都有可能會(huì)產(chǎn)生故障。
例子:
public class Rectangle {
int width;
int height;
public Rectangle(int w, int h){
width = w;
height = h;
}
public int getArea(){
return width*height;
}
}
public class Square extends Rectangle {
public Square(int w, int h) {
super(w, h);
}
public int getArea(){
return width*width;
}
}
public class Test {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle(10, 20);
// Square rectangle = new Square(10, 20);
System.out.println("面積:"+rectangle.getArea());
}
}
如果我們把長(zhǎng)方形類(lèi)Rectangle 替換為正方形類(lèi)Square,那么求出的面積就不正確了,原因是我們繼承的時(shí)候重寫(xiě)了父類(lèi)的getArea方法。這是違背里氏替換原則的。
當(dāng)然,這里只是舉個(gè)例子,實(shí)際項(xiàng)目中我們不會(huì)這樣修改的。
總結(jié):
1. 盡量不要重寫(xiě)父類(lèi)方法,而是增加自己特有的方法。
2. 繼承給程序設(shè)計(jì)帶來(lái)巨大便利的同時(shí),也帶來(lái)了弊端。如果一個(gè)類(lèi)被其他的類(lèi)所繼承,則當(dāng)這個(gè)類(lèi)需要修改時(shí),必須考慮到所有的子類(lèi),并且父類(lèi)修改后,所有涉及到子類(lèi)的功能都有可能會(huì)產(chǎn)生BUG。
相關(guān)文章
kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決
這篇文章主要介紹了kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot中驗(yàn)證用戶(hù)上傳的圖片資源的方法
這篇文章主要介紹了在SpringBoot中驗(yàn)證用戶(hù)上傳的圖片資源,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
mybatis-plus QueryWrapper 添加limit方式
這篇文章主要介紹了mybatis-plus QueryWrapper 添加limit方式,具有很好的參考價(jià)值,希望對(duì)大家有所2022-01-01
java開(kāi)發(fā) 線上問(wèn)題排查命令詳解
這篇文章主要介紹了java開(kāi)發(fā) 線上問(wèn)題排查命令詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
淺析SpringBoot統(tǒng)一返回結(jié)果的實(shí)現(xiàn)
前后端開(kāi)發(fā)過(guò)程中數(shù)據(jù)交互規(guī)范化是一件非常重要的事情,不僅可以減少前后端交互過(guò)程中出現(xiàn)的問(wèn)題,也讓代碼邏輯更加具有條理,下面小編就和大家講講SpringBoot如何統(tǒng)一返回結(jié)果的吧2023-07-07
SpringMVC解析post請(qǐng)求參數(shù)詳解
今天小編就為大家分享一篇解決SpringMVC接收不到ajaxPOST參數(shù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-08-08

