假设您的程序中想要使用B作为A的子类型:
是的,您的代码明显违反了LSK原则。
为什么?
参数应该是逆变的。
这是什么意思?
Liskov原则保证,如果将子类型B替换为基本类型A,则程序的行为不会改变。
或者更准确地说(来自Barbara Liskov,1987):
“如果对于类型B的每个对象o1,都有类型A的对象o2,
使得对于所有定义在A的程序P,在用o2替换o1时,P的行为都不变,
那么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);
p = new RedheadDuck();
p.fly(int.MaxValue);
p = new RubberDuck();
p.fly(int.MaxValue);
}
}
=> 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 < y < 1
你的子类B的foo方法期望的参数值为0 < y < 1
如果你的程序将子类替换成基类,那么在关于值<=0的情况下,你的程序不会按预期运行。
编辑:尽管你在两个foo方法中都使用了double类型作为参数,我假设你通过检查值和它们的范围来保护你的方法。这将导致所描述的失败,类比于示例。
附言:是的,它取决于你为foo定义的合同。假设你想将B用作A的子类型,那么它违反了LSK。否则,它只是一种方法重写。
foo
的契约是什么。您已经描述了特定实现的行为,但没有描述一般契约。 - user2357112