闡述:子型別(subtype)必須能夠替換掉它們的基型別(basetype)
先提出乙個問題:正方形是不是一種特殊的長方形(is - a關係)?
先不要回答這個問題,看下面的分析。
理解:lsp原則的乙個例子,假如有個people的基類,兩個字類man類和woman類,都繼承於people類。那麼針對people類的任何操作,比如fun吃飯、fun睡覺、fun走路,對於man類和woman類都成立。這個很好理解,不管是man還是woman,歸根結底,還都是乙個people。
(一)正常思維
如下例子:
class cshape
;class ccircle:public cshape
;class csquare:public cshape
;在使用cshape物件的任何地方,都可以使用ccircle物件或者csquare物件。
(二)、特殊情況呢?
回到最初的問題,正方形是不是矩形的問題。
如下類:
class crectangle
;class csquare:public crectangel
;假如有個函式
void g(crectangle * r)
r.width = 4;
r.height = 5;
if( r.area() != 20)
break;
請問,對於函式g來說,能用乙個csquare物件,代替crectangle物件嗎?很明顯,不能!
很明顯,違反了lsp原則。
那麼,正方形到底是不似乎矩形呢?也就是說csquare和crectangle之間,是否存在(is - a)關係呢?
解釋:1、從屬性方面講,正方形是矩形,是一種特殊矩形,即width = height;
2、從行為方式將,正方形可能不是矩形。
比如,對於函式g來說,描述了矩形的一種行為方式,很明顯,正方形不符合這種行為方式。
ood中的is-a關係,
是就行為方式而言的,行為方式是可以進行合理假設的。而行為方式,才是我們進行物件導向軟體設計真正所關注的問題。
因此,可以講,正方形不是乙個矩形。
(三)、怎麼處理此類問題呢?
1、基於契約進行設計。
每個類設計時,都會有一些假設,每個方法,都有前置條件,後置條件,這些條件都是契約。對這些方法,要註明契約。
要想從基類派生子類,就必須滿足這些契約。如果不滿足這些契約,就不能繼承出子類。(即使他們看起來很像,比如正方形與矩形)
2、但是我們又需要lsp原則,怎麼辦呢?
從crectangle類和csquare類,提取出公共部分,做為乙個基類。比如cshape類。
crectangle和csquare都繼承自cshape類。
設計模式之六大原則 黎克特制替換原則(LSP)
黎克特制替換原則 liskov substitution principel 是解決繼承帶來的問題。繼承的優點 繼承的缺點 定義 所有引用基類的地方必須能透明地使用其子類的物件。通俗點講,只要父類能出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者可能根本就不需要知道是父類還是...
設計模式之六大原則 黎克特制替換原則(LSP)
黎克特制替換原則 liskov substitution principel 是解決繼承帶來的問題。繼承的優點 繼承的缺點 定義 所有引用基類的地方必須能透明地使用其子類的物件。通俗點講,只要父類能出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者可能根本就不需要知道是父類還是...
PHP物件導向五大原則之黎克特制替換原則 LSP 詳解
替換原則由mit電腦科學實驗室的liskov女士在1987年的oopsla大會上的一篇文章中提出,主要闡述有關繼承的一些原則,故稱黎克特制替換原則。2002年,robert c.martin出版了一本名為 agile software development principles patterns ...