2011-12-21 93 views
5

比方說,我們有這個真是小巫見大巫類:里氏替換原則 - 壓倒一切的方法例如

class A 
{ 
    virtual int Function(int number) 
    { 
     return number; 
    } 
} 

class B : A 
{ 
    override int Function(int number) 
    { 
     return number + 1; 
    } 
} 

class UseExample 
{ 
    void Foo(A obj) 
    { 
     A.Function(1); 
    } 
} 

將這個例子違反了LSP的?如果是這樣,你能給我一個不違反原則並使用不同實現的例子嗎?

這個怎麼樣:

class B : A 
{ 
    int variable; 

    override int Function(int number) 
    { 
     return number + variable; 
    } 
} 

據我瞭解使用可變「變量」導致更強的先決條件,因此它違反了LSP的。但是當我使用多態性時,我不完全確定如何遵循LSP。

+1

因爲你的函數沒有任何合同,所以返回任意值的實現是完全可以接受的。但是,如果您在函數名稱中指定了一個合約,則會進入灰色區域,如下所示:int Add1ToArgument(int argument){...} – Polity 2011-12-21 02:53:46

+0

Polity,方法命名中隱含的語義並不真正進入它。它來自類型定義。 – 2011-12-21 02:55:44

+0

如果語義與原理無關,你會介意給我解釋一下Rectangle/Square的例子嗎?市長抱怨說,我發現迄今爲止,如果您使用Rectangle obj = new Square()並且在未事先知道該對象是Square的情況下分配高度寬度,則會得到函數getArea的意外結果()只是因爲你認爲一個Rectangle對於Height和Width有兩個不同的值。在此先感謝 – BizTuk 2011-12-21 03:07:22

回答

2

這是有效的,在這兩種情況下,它都沒有違反原則。 B可以代替A.它只是具有不同的功能。

一個簡單的方法來撕毀合同將扔在燒烤異常覆蓋如果數== 23或東西:)

+0

在第二個例子中,讓我們說我們調用函數A.Function(1)和變量「變量」未被初始化。在這種情況下,我們有一個運行時錯誤(如果我沒有弄錯),所以我們違反了LSP。我相信你不能交換B/A,因爲A沒有定義「變量」 – BizTuk 2011-12-21 03:11:52

+0

int是默認初始化的,它不能被初始化(儘管這裏沒有指定語言,我假設C#ish)。 B建築可以完全不同於A建築,只要它可以作爲一個A構建就可以使用。例外情況很可能是微妙地破壞LSP的事情。但是,如果你引入A.Function可以拋出異常的想法,你可以覆蓋你的屁股:) – 2011-12-21 03:35:39

+0

我的int初始化錯誤。你可以解決這個例子,並使用一個沒有默認構造函數的C類對象,並且在B的方法中使用一個幻數。這樣你可以期待A.Function()拋出的異常(應該是obj.Function(),而不是)。 感謝您的回覆:P – BizTuk 2011-12-21 04:04:31

0

從我對它的理解,我會說,無論你的例子違反LSP作爲子類不能被它的超類取代。 考慮以下幾點:

class UseExample { 
    void Foo(A& obj, int number) { 
     int retNumber = obj.Function(number); 
     assert(retNumber==number); 
    } 
} 

如果你要傳遞給B對象爲富斷言將失敗的參考。 B.Function正在改變A.Function的後置條件。 Foo客戶端代碼不應該知道可能會破壞其代碼的可能子類型。