2012-07-12 31 views
2

你可以有一個超類Shape,Square和Rectangle是兩個子類,但是你可以有Square子類Rectangle,因爲Square是一個特殊的矩形,四邊相等。Square和Rectangle可以繼承Shape,但可以Square子類Rectangle?

我試圖使用這樣一個原則來檢查,即每當使用超類時,它應該能夠被其子類替換,但是如果使用子類,則可能無法被其超類替換類。看起來很好,但我總是覺得Square不能成爲Rectangle的孩子出於某種原因?任何人都能給我一些亮光嗎?

回答

3

您指的是Liskov Substition Principle

可替代性是面向對象編程的一個原則。它指出,在一個計算機程序中,如果S是T的一個子類型,那麼類型T的對象可以用類型S的對象代替(即,類型S的對象可以代替類型T的對象),而不改變任何該程序的理想屬性(正確性,執行的任務等)。

具體到你的問題:

違反LSP是正方形類從一個矩形類派生,假設二者的寬度和高度存在獲取和設置方法的典型例子。 Square類始終假設寬度與高度相等。如果在需要Rectangle的上下文中使用Square對象,則可能會發生意外的行爲,因爲Square的尺寸不能單獨修改(或者不應該)。這個問題不容易修正:如果我們可以在Square類中修改setter方法,以便它們保留Square不變量(即保持尺寸相等),那麼這些方法將削弱(違反)Rectangle設置器的後置條件,說明尺寸可以獨立修改。違反LSP,像這樣,在實踐中可能會也可能不會成爲問題,這取決於使用違反LSP的類的代碼實際預期的後置條件或不變量。可變性是一個關鍵問題。如果Square和Rectangle只有getter方法(即它們是不可變對象),則不會發生違反LSP的情況。

用簡單的英語,則無法使用其中一個Rectangle預期,因爲廣場有行爲的Rectangle沒有一個廣場。如果有人試圖使用他們認爲應該是Rectangle的實例,但它確實是Square的一個實例,他們可能會設置寬度並且會驚訝高度會自動更改(意外的副作用)。

+0

只是作爲一個nitpicker:一個不可變的矩形可能是一個方形的子類... – 2012-07-12 05:14:07

+0

無論如何有一個方形的背後有什麼想法?如果所有方面都相同,它就變成了一個正方形。所以作爲一個正方形,更像是一種財產,而不是一種行爲。如果將其視爲行爲,則必須分別處理縮比三角形,圓/橢圓等。如果僅僅實施一種輔助方法,它會更有意義嗎? 'setSide(...)'是標準的,'setSides(...)'將同時設置所有的(並且以這種方式創建一個正方形)。在我看來,在這種情況下,我們從「結果」中獲取屬性並將其轉換爲功能。 – Katai 2012-07-12 07:20:16

+0

@Anders:的確如此:-)這是在維基百科報價的最後兩句中說明的。 – 2012-07-14 17:02:52