理論性知識
定義里氏替換原則,Liskov Substitution principle(LSP)。
抽象定義是下面這樣的
如果對每一個型別為T1的物件O1,都有型別為T2的物件O2,使得以T1定義的所有程式P在所有的物件O1都替換成O2時,程式P的行為沒有發生變化,那麼型別T2是型別T1的子型別。
通俗地解釋一下
一個軟體實體如果適用一個父類的話,那一定適用於其子類,所有引用父類的地方必須能透明地使用其子類的物件,子類物件能夠替換父類物件,而程式邏輯不變。
引申一下,如果子類替換父類,還必須保證程式邏輯不變,就必須滿足以下幾點。
子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法。 子類中可以增加自己特有的方法。 當子類的方法過載父類的方法時,方法的前置條件(即方法的輸入,入參)要比父類方法的輸入引數更寬鬆。當子類的方法實現父類的方法時(重寫,過載或實現抽象方法),方法的後置條件(方法的輸出,返回值)要比父類更嚴格或相等。 優點加強程式的健壯性,同時變更時可以做到非常好的相容性。
提高程式的維護性,擴充套件性,降低需求變更時引入的風險。
程式碼實戰1
實現一個正方形繼承長方形的場景,因為正方形是一種特殊的長方形。
定義一個長方形,如下圖
定義一個正方形,如下圖,重寫了父類的方法。
最後執行測試方法,當寬大於等於高時,就改變寬和高。如下圖
當用子類正方形替換父類時,程式就會進入無限迴圈,如下圖
根據以上得出,子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法
程式碼實戰2
首先定義一個簡單的父類,如下圖
然後定義一個子類,子類的入參型別Map比父類的入參HashMap寬鬆,如下圖
最後測試如下圖
由測試結果可以看出,child類完全可以替換base類去執行。遵循了裡式替換原則,
即當子類的方法過載父類的方法時,方法的前置條件(即方法的輸入,入參)要比父類方法的輸入引數更寬鬆。
程式碼實戰3
還是定義一個簡單的父類,方法返回型別為HashMap,如下圖
定義一個子類,實現父類抽象方法時,返回值型別為Map,編譯器就會直接報錯,如下圖
根據以上可以得出結論
當子類的方法實現父類的方法時(重寫,過載或實現抽象方法),方法的後置條件(方法的輸出,返回值)要比父類更嚴格或相等。
個人總結
一開始學習裡式替換原則時,也是不明白。最後也是慢慢理解透的。總結起來就是
子類可以替換父類,替換後,不能改變程式的執行邏輯。