2016-12-29 93 views
2

如所述here里氏替換原則違反

行爲亞型的里氏的概念定義 可替代性的一個對象的概念;也就是說,如果S是T的子類型,那麼在程序中類型T的對象可以用類型S 的對象代替而不改變該程序的任何期望屬性(例如 正確性)。

假設,我們有下一個類層次結構:

  1. 的基礎上,抽象類 - AnimalWithFur。它具有隻讀屬性furColor,這應該在後繼中被覆蓋。
  2. 基類的後繼者 - Cat,它覆蓋了furColor並返回灰色。
  3. 貓的繼任者 - 老虎,它覆蓋furColor和收益剝離

然後,我們聲明瞭一個方法,它有一個類型貓(不AnimalWithFur)的參數。向該方法發送Tiger實例會違反SOLID中的L原則嗎?

回答

4

嚴格來說,是的。里氏的wiki文章總結說:

「......在一個程序......在不改變任何理想特性節目」

如果你去回到Barbara Liskov的original paper,它的字面上更嚴格在其措辭,3.3。 類型層次

如果S型的每一個對象O1有類型T的對象O2使得對於所有程序P IN的T來定義,P 的行爲是不變當O1代替O2

(Empahsis礦)

所以,如果你與另一個實例,做不同的東西,即returnin取代Cat實例摹剝離不是灰色的,那麼這是一個里氏違反原來的意義,因爲一個程序可以很容易地定義依賴於顏色是灰色的,在這裏:

program(Cat c){ 
    println(c.furColor); 
} 

該程序的行爲可能會改變如果你通過它Tiger代替Cat

但是,如果您沒有添加額外的前提條件或後置條件,那麼以正常方式應用LSP並不違反。這是一個更實用,更不科學的定義,因爲人們接受在用另一個實體替換一個具體類型的實例時打算改變程序的行爲,同時保持該程序的理想屬性。所以假設客戶端代碼可以像其他顏色一樣處理剝離,並且灰色對於程序的「合意」屬性不是必需的,那麼它不會違反。

+0

重寫參數類型爲AnimalWithFur改變了什麼? –

+0

不,因爲屬性furColour在AnimalWithFur上。而且你還在用一隻老虎替代一隻貓,因爲我必須假設,如果你考慮LSP,你代替了,你只有兩種具體類型;貓和老虎。 – weston

+0

甚至可能不關心實際定義的屬性的位置,如果它改變了程序的理想屬性,那麼它就是LSP違例。 – weston

1

簡答:不一定。我不會說你提供的信息。對我而言,關鍵在於你沒有說出想象中的新方法應該做什麼。

您可能會認爲您在新方法中要求的行爲比類層次結構的關注更重要。

做到這一點的一種方法是爲傳入的實例/參數中新方法需要的行爲定義一個接口。

然後,無論您想要傳入該方法的哪個類都可以實現該接口,並且可以分開繼承層次結構的關注點並轉而關注行爲的一致性。

1

您的問題很好地描述了爲什麼要使用類組合而不是類繼承。首先,你的代碼是不合邏輯的 - Tiger不是Cat在你的意義上,TigerCats family.之一從代碼的角度來看,重寫並完全替代父類的行爲是不好的設計,這實際上是liskov替換違例 - 你的Cat class表示具有某種具體顏色的已定義的cat,並且應用程序期望分別與它一起工作,但是您使用不一致的類型覆蓋它並更改行爲。 如果您要正確描述類型層次結構,那麼您將擁有抽象類型Cat而不使用furColor,並且類型爲TigerHomeCat,但HomeCat可能具有不同的顏色,是不是?

如果你想有一個微不足道的例子,例如: 你正在擴展List接口與自定義實現,返回大小總是10,但與不同數量的對象內。每個正常的應用程序都希望使用for語句來處理列表,但由於您破壞了LS原則,並且List對象的行爲並不像預期的那樣,所以會出現不可預知的行爲。

+0

我並不完全同意你關於類的層次結構,但即使有你的評論 - 我的代碼僅僅是一個例子,它並沒有被設計成最好的解決方案:)很容易理解和繪製與現有的並行,並使用廣泛的例子,至於我。不過,我喜歡你關於作文的注意事項。好評 –

相關問題