2里氏替換原則
阿新 • • 發佈:2020-11-23
里氏替換原則
里氏替換原則的英文名稱是:Liskov Substitution Principle,簡稱LSP(老色批)。1里氏替換原則的定義
英文定義有兩種:①If for each object o1 of type S there is an object o2 of type T such thatfor all programs P defined in terms of S,the behavior of P is unchangedwhen o1 is substituted for o2 then T is a subtype of S.這個定義是最正宗的定義,意思是:如果對一個型別為S的物件o1,都有型別為T的物件o2,使得以S定義的所有程式P在所有的物件o1都代換成o2時,程式P的行為沒有發生變化,那麼型別T是型別S的子型別。②Functions that use pointers or references to base classes must be ableto use objects of derived classes without knowing it.第二個定義意思是:所有引用基類的地方必須能透明地使用其子類物件。清晰明確地說明只要父類能出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者可能根本就不需要知道父類還是子類;但是反過來則不可以,有子類的地方,父類未必就能適應。里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。LSP 是繼承複用的基石,只有當派生類可以替換掉基類,且軟體單位的功能不受到影響時,基類才能真正被複用,而派生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關係就是抽象化的具體實現,
繼承存在很多優點,但也存在缺陷,而“里氏替換原則”可以減少"弊"所帶來的麻煩。優點:■ 程式碼共享,減少建立類的工作量,每個子類都擁有父類的方法和屬性;■ 提高程式碼的可重用性;■ 提高程式碼的可擴充套件性;■ 提高產品或專案的開放性。
缺陷:■ 繼承是入侵式的。只要繼承,就必須擁有父類的所有屬性和方法;■ 降低程式碼的靈活性。子類必須擁有父類的屬性和方法,使子類受到限制;■ 增強了耦合性。當父類的常量、變數和方法修改時,必須考慮子類的修改,這種修改可能造成大片的程式碼需要重構。
2里氏替換原則的應用
在編譯期間,java語言編輯器會檢查一個程式是否符合里氏替換原則,這是一個無關實現的、純語法意義上的檢查。里氏替換原則要求是使用基類的地方,子類一定適用,因此子類必須具備基類的全部介面。或者說,子型別的介面必須包括全部的基類的介面,而且還有可能更寬。如果一個java程式破壞這一條件,java編輯器就會在編譯程式時丟擲錯誤提示,並停止編譯。例如,一個基類Base聲明瞭一個public方法改換成private或procted。即子類不能下面編寫一個測試類
上述程式碼中,使用基類物件指向子類是允許的,但反過來,使用子類物件指向父類則違反里氏替換原則,會出現錯誤。public class Test{ public static void main(String[] args){ //宣告一個基類物件 Animal animal; //使用基類物件指向子類 animal = new Horse(); animal.move; animal = new Bird(); animal.move; // Horse h = new Animal(); //錯誤 } }
注意按照里氏替換原則,當多個類之間存在繼承關係時,通常應該使用父類或介面來指向子類的物件(除非需要使用子類特有的方法),這更利於提高系統的可擴充套件性。
在設計模式中體現里氏替換原則的有如下幾個模式:■ 策略模式■ 組合模式■ 代理模式
來自為知筆記(Wiz)