我有以下代码
public class A
{
public double foo(double y)
{
return real_value;
}
}
其中foo
方法-1 < y < 1
的输入和函数的结果是大于零的实数。
然后我有了继承的class B
,该继承了class A
并覆盖了方法foo
。
public class B extends A
{
public override double foo(double y)
{
return real_value;
}
}
其中foo
方法0 < y < 1
的输入和函数的结果是任何实数。
这里是否违反了利斯科夫换人原则?
提前谢谢。
答案 0 :(得分:1)
假设您要在程序中将B用作A的子类型:
是的,您的代码显然违反了LSK。
为什么?
争论应该是矛盾的。
这是什么意思?
Liskov Principle保证,如果将子类型B替换为基本类型A,则程序的行为不变。
或更准确地说(Barbara Liskov,1987年):
“如果对于类型B的每个对象o1,都有一个类型A的对象o2
这样,对于以A定义的所有程序P,P的行为都不会改变
当用o1代替o2时,则B是A”的子类型。
例如:
class Duck { void fly(int height) {} }
class RedheadDuck : Duck { void fly(long height) {} }
class RubberDuck : Duck { void fly(short height) {} }
class LSPDemo
{
public void Main()
{
Duck p;
p = new Duck();
p.fly(int.MaxValue); // Expected behaviour
p = new RedheadDuck();
p.fly(int.MaxValue); // OK
p = new RubberDuck();
p.fly(int.MaxValue); // Fail
}
}
=> the program behaves unchanged, if the argument is contravariant.
=> e.g. base type <= sub type
=> RubberDuck violates this principle, as it does not allow all values of the base type Duck
在您的代码中,基类A foo的类型将期望参数值-1
编辑:尽管您在两个foo方法上都将double类型用作参数,但我假设您通过检查值及其作用域来保护自己的方法。类似于示例,这将导致所描述的失败。
P.S .:是的,这取决于您为foo定义的合同。假定您要使用B作为A的子类型,则它违反了LSK。否则,它只是方法的重载。
答案 1 :(得分:0)
实际上,您的重写函数违反了基本函数的约定,因此Liskov原理在此并不是真正有用。但是,如果您在基本函数中添加“处理模式”之类的参数,则L原理可以正常工作(对于所有旧处理情况,被覆盖的函数都会调用基本函数)。