2011-12-21 94 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客户端代码不应该知道可能会破坏其代码的可能子类型。