面向對象原則之里氏替換原則

一.簡稱

英文全稱是Liskov Substitution Principle, 縮寫是LSP

二.定義

如果對每一個類型為S的對象O1,都有類型為T的對象O2,使得以T定義的所有程序P在所有的對象O1都替換成O2時,程序P的行為沒有發生變化,那么類型S是類型T的子類型。
簡單的說就是所有引用基類的地方必須能透明地使用其子類的對象。通俗點講,只要父類能出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者根本就不需要知道是父類還是子類,但是反過來就不行,有子類出現的地方,父類未必就能適應。總的來說就是抽象。

比如從Window和View的關系來看

window.png
//窗口類
public class Window{
  public void show(View child){
    child.draw();
  }
}
//測量視圖的寬高為公用代碼,繪制實現交給具體的子類
public abstract class View{
  public abstract void draw();
  public void measure(int width,int height){
          //測量視圖大小
  }
}
//TextView 的具體實現
public class TextView extends View{
   public void draw(){


   }
}
//Button的具體實現
public class Button extends View{
   public void draw(){

  }
}

Window依賴于View,而View定義了一個視圖抽象,measure是各個子類共享的方法,子類覆寫View的draw方法實現自己特有的功能,任何繼承自View類的子類都可以設置給View方法,就是所說的里氏替換。通過里氏替換,就可以定義各式各樣的View,然后傳遞給Window,Window負責將View顯示到屏幕上。

三.核心原理

核心是抽象,而抽象又依賴于繼承特性。
繼承的優缺點:
優點:
(1)代碼復用,減少創建類的成本,每個子類都擁有父類的方法和屬性
(2)子類和父類基本相似,但又與父類有所區別
(3)提高代碼的可擴展性
缺點:
(1)只要繼承就必須擁有父類的所有屬性和方法
(2)可能造成子類代碼冗余、靈活度降低,因為子類必須擁有父類的屬性和方法。
在實際使用中要根據具體的情況來看要不要使用繼承。

四.注意事項

(1)子類的所有方法必須在父類中聲明,或子類必須實現父類中聲明的所有方法。因為根據里氏替換原則,為了保證系統的擴展性,在程序中通常使用父類來進行定義,如果一個方法只存在子類中,在父類中不提供相應的聲明,則無法在以父類定義的對象中使用該方法。
(2)盡量把父類設計為抽象類或接口,讓子類繼承父類或實現父接口,并實現父類中聲明的方法,運行時,子類實例替換父類實例,我們可以很方便地擴展系統的功能,同時無須修改原有子類的代碼,增加新的功能可以通過增加一個新的子類來實現。里氏替換原則是開閉原則的具體實現手段之一。

總結

里氏替換原則和開閉原則一般都是一起使用的,通過里氏替換來達到對擴展開放,對修改關閉的效果。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容