## 一、繼承的問題
>我們知道Java的三大特性:封裝,繼承,多態。Java 繼承有很多優點,是減少重復代碼的可靠手段。
但是繼承同時存在一些`缺點`:
1.類的耦合性增加了。比如父類更改之后子類也同時需要更改
2.降低代碼靈活性。因為繼承時,父類會對子類有約束性
我們使用`里氏替換原則`,可以減少繼承帶來的問題。
## 二、定義
```
里氏替換原則(LSP)指的是所有引用基類的地方都可以透明的使用其子類的對象
可以理解為:只要有父類出現的地方,都可以使用子類來替代。而且不會出現任何錯誤或者異常。
但是反過來卻不行。子類出現的地方,不能使用父類來替代。
如果不符合上述的規定的話,我們可以想象子類的實例化調用方法時候,調用的卻是父類的方法。
會出現意想不到的結果
```
## 三、具體約束
1. 子類必須實現父類的抽象方法,但不得重寫父類的非抽象(已實現的)方法。
2. 子類中可增加自己特有的方法。(可以隨時擴展)
3. 當子類覆蓋或者實現父類的方法時,方法的前置條件(方法形參)要比父類輸入參數更加寬松。
否則會調用到父類的方法。
4. 當子類的方法實現父類的抽象方法時,方法的后置條件(即方法的返回值)要比父類更嚴格。
否則會調用到父類的方法。
>在講開閉原則的時候埋下了一個伏筆,在獲取折扣時重寫覆蓋了父類的 getPrice() 方法,增加了一個獲取原價的方法 getOriginPrice(),顯然就違背了里氏替換原則。我們修改一下代碼,不應該覆蓋 getPrice() 方法,增加 getDiscountPrice() 方法:
~~~
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
public Double getDiscountPrice() {
return super.getPrice() * 0.61;
}
}
~~~
>里氏替換原則只存在于父類與子類之間,約束繼承泛濫
## 四、最佳實踐
>我們最好將父類定義為抽象類,并定義抽象方法,讓子類重新定義這些方法,
當父類是抽象類時候,父類不能實例化
- 前言
- 第一章 設計七大原則
- 第1節 開閉原則
- 第2節 依賴倒置原則
- 第3節 單一職責原則
- 第4節 接口隔離原則
- 第5節 迪米特法則
- 第6節 里氏替換原則
- 第7節 合成復用原則
- 第二章 簡單工廠模式
- 第1節 使用場景
- 第2節 示例代碼
- 第三章 創建者模式
- 第1節 工廠方法模式
- 第2節 抽象工廠模式
- 第3節 建造者模式
- 第4節 原型模式
- 第5節 單例模式
- 第四章 結構型模式
- 第1節 適配器模式
- 第2節 橋接模式
- 第3節 組合模式
- 第4節 裝飾者模式
- 第5節 外觀模式
- 第6節 享元模式
- 第7節 代理模式
- 第五章 行為模式
- 第1節 責任鏈模式
- 第2節 命令模式
- 第3節 迭代器模式
- 第4節 中介者模式
- 第5節 備忘錄模式
- 第6節 觀察者模式
- 第7節 狀態模式
- 第8節 策略模式
- 第9節 模板方法模式
- 第10節 訪問者模式
- 第11節 解釋器模式