「乙個軟體實體如果使用的是乙個基類的話,一定適用於其子類,而且根本不能覺察出基類物件和子類物件的區別。」
陳述:
barbara liskov對原則的陳述:
若對每個型別s的物件o1,都存在乙個型別t的物件o2,使得在所有針對t編寫的程式p中,用o1替換o2後,程式p的行為功能不變,則s是t的子型別。
通俗地講,就是
子型別能夠完全替換父型別,而不會讓呼叫父型別的客戶程式從行為上有任何改變。
意義:
我們在客戶程式在呼叫某乙個類時,實際上是對該類的整個繼承體系設定了一套約束,繼承體系中的所有類必須遵循這一約束,即
前置條件和後置條件必須保持一致
。這為物件繼承加上了一把嚴格的枷鎖。顯然,lsp原則對於約束繼承的氾濫具有重要意義。
分析:
例如:基類base,派生類derived,派生類例項d,函式f(base* p);
顯然d對於f是脆弱的。
經典例子:長方形與正方形駁論
class rectangle
long getwidth()
void setheight(long height)
long getheight()
};//正方形類
class square
long getside()
};
//正方形類(如果繼承自長方形類):
class square : public rectangle
long getwidth()
void setheight(long height)
long getheight()
long getside()
void setside(long side)
};
class smarttest}};
從上面小函式可見,只想改變長方形的寬時,如果把正方形看成一種長方形的話,則正方形的長和寬都被改變了。lsp原則被破壞了,square不應成為rectangle的子類。
結論:
黎克特制代換與通常的數學法則和生活常識有不可混淆的區別。
考慮乙個設計是否恰當時,不能孤立的看待並判斷,應該從此設計的使用者所作出的假設來審視它!
思考:
這個看似明顯正確的模型怎麼會出錯呢?
「正方形是一種長方形」
對不是smarttest函式的編寫者而言,正方形可以是長方形,但是對smarttest函式的編寫者而言,square絕對不是rectangle!!
ood中物件之間是否存在is-a關係,應該從行為的角度來看待。
->而行為可以依賴客戶程式做出合理的假設。
改進:
引入乙個quadrangle(四邊形)類,並將rectangle 與square變成它的具體子類,解決了rectangle 與square的關係不符合黎克特制替換原則的問題。
class quadrangle
;
quadrangle類只宣告兩個取值方法,不宣告任何的賦值方法。
//長方形類:
class rectangle : public quadrangle
long getwidth()
void setheight(long height)
long getheight()
};
//正方形類:
class square : public quadrangle
long getside()
long getwidth()
long getheight()
};
問題如何得以避免?基類quadrangle類沒有賦值方法,因此類似於 smarttest的resize()方法不可能適用於quadrangle型別,而只能適用於不同的具體子類rectangle 和square,因此黎克特制替換原則不可能被破壞。
結論:
相應設計模式:
參考資源:
《設計模式:可復用物件導向軟體的基礎》,erich gamma richard helm ralph johnson john vlissides著作,李英軍 馬曉星 蔡敏 劉建中譯,機械工業出版社,2005.6
《敏捷軟體開發:原則、模式與實踐》,robert c. martin著,鄧輝譯,清華大學出版社,2003.9
《設計模式解析》,alan shalloway等著(徐言聲譯),人民郵電出版社,2006.10
Liskov替換原則
2.3.3 liskov替換原則 barbara liskov於1988年提出了著名的替換原則 如果對於型別s的每個物件o1存在型別t的物件o2,那麼對於所有定義了t的程式p來說,當用o1替換 o2並且s是t的子型別時,p的行為不會改變。通俗地講,就是子型別能夠完全替換父型別,而不會讓呼叫父型別的客...
軟體設計原則 黎克特制替換原則
liskov substitution principle 黎克特制替換原則 定義 如果對每一型別為t1的物件o1,都有型別為t2的物件o2,使得以t1定義的所有程式p在所有的物件o1都替換成o2時,程式p的行為沒有發生變化,那麼型別t2是型別t1的子型別。擴充套件 乙個軟體實體如果適用乙個父類的話...
Liskov替換原則(LSP)
注 摘自 敏捷軟體開發 原則 模式與實踐 robert c.martin 對於lsp可以做如下解釋 子型別 subtype 必須能夠替換掉它們的基型別 base type barbara liskov首次寫下這個原則是在1988年。她說到,這裡需要如下替換性質 若對每個型別s的物件o1,都存在乙個型...