代碼共享,減小建立類的工做量,每一個子類都擁有父類的方法和屬性;設計
提升代碼的重用性對象
子類能夠形似父類,但又異於父類。繼承
提升代碼的可擴展性,實現父類的方法就能夠「隨心所欲」了。接口
提升產品或項目的開放性。開發
繼承是侵入性的。只要繼承,就必須擁有父類的全部屬性和方法;產品
下降代碼的靈活性。子類必須擁有父類的屬性和方法,讓子類的自由世界裏多了些約束it
加強了耦合性。當父類的常量、變量和方法被修改時,須要考慮子類的修改,並且在缺少規範的環境下,這種修改可能帶來很是糟糕的結果--大段代碼須要重構。io
第一種定義,也是最正宗的定義:If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(若是對每個類型爲S的對象o1,都有類型爲T的對 象o2,使得以T定義的全部程序P在全部的對象o1都代換成o2時,程序P的行爲沒有發生變 化,那麼類型S是類型T的子類型。)class
第二種定義:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(全部引用基類的地方必須能透明地使用其子類的 對象。)變量
第二個定義是最清晰明確的,通俗點講,只要父類能出現的地方子類就能夠出現,並且 替換爲子類也不會產生任何錯誤或異常,使用者可能根本就不須要知道是父類仍是子類。但 是,反過來就不行了,有子類出現的地方,父類未必就能適應。
里氏替換原則爲良好的繼承定義了一個規範,一句簡單的定義包含了4層含義。
子類必須徹底實現父類的方法:注意 在類中調用其餘類時務必要使用父類或接口,若是不能使用父類或接口,則說明 類的設計已經違背了LSP原則。
子類能夠有本身的個性
覆蓋或實現父類的方法時輸入參數能夠被放大:(方法中的輸入參數稱爲前置條件,這是什麼意思呢?你們作過Web Service開發就應該知 道有一個「契約優先」的原則,也就是先定義出WSDL接口,制定好雙方的開發協議,而後再 各自實現。里氏替換原則也要求制定一個契約,就是父類或接口,這種設計方法也叫作 Design by Contract(契約設計),與里氏替換原則有着殊途同歸之妙。契約制定了,也就同 時制定了前置條件和後置條件,前置條件就是你--父類要讓我--子類執行,就必須知足個人條件;後置條 件就是我執行完了須要反饋,標準是什麼。)
覆寫或實現父類的方法時輸出結果能夠被縮小:(這是什麼意思呢,父類的一個方法的返回值是一個類型T,子類的相同方法(重載或覆 寫)的返回值爲S,那麼里氏替換原則就要求S必須小於等於T,也就是說,要麼S和T是同一 個類型,要麼S是T的子類,爲何呢?分兩種狀況,若是是覆寫,父類和子類的同名方法的 輸入參數是相同的,兩個方法的範圍值S小於等於T,這是覆寫的要求,這纔是重中之重,子 類覆寫父類的方法,天經地義。若是是重載,則要求方法的輸入參數類型或數量不相同,在 里氏替換原則要求下,就是子類的輸入參數寬於或等於父類的輸入參數,也就是說你寫的這 個方法是不會被調用的,參考上面講的前置條件。)
採用里氏替換原則的目的就是加強程序的健壯性,版本升級時也能夠保持很是好的兼容 性。即便增長子類,原有的子類還能夠繼續運行。在實際項目中,每一個子類對應不一樣的業務 含義,使用父類做爲參數,傳遞不一樣的子類完成不一樣的業務邏輯,很是完美!
在項目中,採用里氏替換原則時,儘可能避免子類的「個性」,一旦子類有「個性」,這個子 類和父類之間的關係就很難調和了,把子類當作父類使用,子類的「個性」被抹殺——委屈了 點;把子類單獨做爲一個業務來使用,則會讓代碼間的耦合關係變得撲朔迷離——缺少類替 換的標準。