設計模式六大原則之(二)---里氏替換原則

        肯定有不少人跟我剛看到這項原則的時候一樣,對這個原則的名字充滿疑惑。其實原因就是這項原則最早是在1988年,由麻省理工學院的一位姓裏的女士(Barbara Liskov)提出來的。

  定義1:如果對於每個類型爲T1的對象o1,都有類型爲T2的對象O2,使得以T1定義的所有程序p在所有的對象o1替換成o2時,程序p的行爲沒有發生變化,那麼類型T2是T1的子類型

 定義2:所有引用基類的地方必須能透明的使用其子類的對象


問題由來:有一功能p1,由類A完成,先需要將功能p1進行擴展,擴展後的功能爲P,其中P由原功能P1和新功能P2組成。新功能P由類A的子類B來完成,則子類B在完成新功能P2的時候,有可能導致原功能p1發生故障


解決方案:在使用繼承時,遵循里氏替換原則,類B繼承類A時,除了添加新的方法完成新的功能P2時,儘量不要重寫基類A的方法,也不要重載基類A的方法

     繼承包含這層含義:基類中已經實現了的方法(相對於抽象方法而言),實際上是設定一系列的規範和契約,雖然它不要求所有的子類都必須遵從這些契約,如果子類對這些非抽象的方法重寫或者任意修改,會對整個繼承體系造成破壞,而里氏替換原則就是表達了這層含義.

   繼承作爲面向對象的三大特徵之一,在給程序設計帶來便利的同時,也帶來了弊端,比如使用繼承會給程序帶來侵入性,程序的可移植性降低,增加對象間的耦合性,如果一個類被其他類所繼承時,當這個類需要修改時,必須考慮到所有的子類,且基類修改後,所有涉及到子類的功能都有可能產生故障


如果非要重寫基類的方法,比較通用的做法是:原來的基類和子類都繼承一個更通俗的基類,原有的繼承關係去掉,採用依賴、聚合,組合等關係代替。

 

里氏替換原則通俗的來講就是:子類可以擴展基類的功能,但不能改變基類所有的功能,它包含以下4點:

(1)、子類可以實現基類的抽象方法,但是不能重寫基類的非抽象方法

(2)、子類可以增加自己獨有的方法

(3)、當子類的方法重載(寫)基類的方法時,方法的前置條件(即方法的形參)要比基類方法的輸入更寬鬆

(4)、當子類的方法實現基類的抽象方法時,方法的後置條件(即方法的返回值)要比基類更嚴格

 

     看上去很不可思議,因爲我們會發現在自己編程中常常會違反里氏替換原則,程序照樣跑的好好的。所以大家都會產生這樣的疑問,假如我非要不遵循里氏替換原則會有什麼後果?

        後果就是:你寫的代碼出問題的機率將會大大增加。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章