抽象属性是否违反里氏替换原则?
假设我有一个抽象类,例如:
public abstract class Pet {
private final String name;
public Pet(String name) {
this.name = name
};
public abstract boolean getsSpecialTreatment();
}
public final class Dog extends Pet {
@Override public boolean getsSpecialTreatment() { return true; }
}
public final class Cat extends Pet {
@Override public boolean getsSpecialTreatment() { return false; }
}
我的程序将根据是否设置特殊处理标志来不同地对待 Pet
。我的问题是这是否违反了里氏替换原则,该原则指出:
[...] 在计算机程序中,如果 S 是 T 的子类型,则类型 T 的对象可以替换为 S 类型的对象 [...] 而不改变该对象的任何所需属性程序(正确性、执行的任务等)。
Suppose I have an abstract class like:
public abstract class Pet {
private final String name;
public Pet(String name) {
this.name = name
};
public abstract boolean getsSpecialTreatment();
}
public final class Dog extends Pet {
@Override public boolean getsSpecialTreatment() { return true; }
}
public final class Cat extends Pet {
@Override public boolean getsSpecialTreatment() { return false; }
}
My program will treat Pet
s differently depending on whether the special treatment flag is set. My question is whether this counts as violating the Liskov substitution principle, which states that:
[...] in a computer program if S is a subtype of T, then objects of type T may be replaced with objects of type S [...] without altering any of the desirable properties of that program (correctness, task performed, etc.).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在这种情况下,这些类的用户可能会写:
此代码适用于两种情况,因此您不会违反 LSP。但是,如果您
这样做了,那么您将违反 LSP,因为使用
UnknownAnimal
实例时现有代码将被破坏。In this case, users of those classes will probably write:
This code will work on both cases, so you would not be violating LSP. However, if you had
then you would be violating LSP, because existing code will break when using
UnknownAnimal
instances.不会。程序中该方法的任何使用都将基于返回值做出后续决策,就像任何其他方法一样。由于该方法存在的本质,任何程序都不应对其结果做出假设。因此,此方法返回值的更改不应更改程序的属性。
No. Any usage of the method in the program would base subsequent decisions on the return value, just like any other method. By the very nature of the existence of the method, no program should make assumptions as to its outcome. Therefore the change in the value returned by this method should not change the properties of the program.
首先,强烈反对您对猫的歧视!
现在,当程序员引用所谓的“里氏替换原则”时,他们并不是真正在学术意义上谈论它。我们一定是在某种非正式的、粗俗的、混蛋的意义上使用它的。
这是什么意义?我发现这只不过是要求子类必须符合超类设定的契约。所以真的很无趣。人们引用这句话只是为了炫耀。
First, strong objection to your discrimination against cats!
Now, when programmers invoke the so called "Liskov substitution principle", they are not really talking about it in its academic sense. We must be using it in some informal, vulgar, bastardized sense.
What sense is that? I find it nothing more than requiring that subclass must conform to the contract set by the super class. So it's really uninteresting. People invoke this phrase just to be fansy.
这取决于合同。也就是说,使用类的代码必须获得一致的行为,无论它使用什么类型的派生。
如果合同规定“getSpecialTreatment”始终返回 true,那么您将在派生类中违反这一规定。
如果合约规定“getSpecialTreatment”返回一个确定 blabla. 的布尔值,那么您就没有违反 LSP。
如果引入了基类中不存在的附加约束,则可能会违反 LSP。
It depends on the contract. That is, the code using your classes must get consistent behavior, regardless what derivation of your type is it using.
If the contract stated "getSpecialTreatment" always returns true, you would be violating that in your derived class.
If the contract states "getSpecialTreatment" returns a boolean value determining blabla., then you are not violating LSP.
You could violate LSP if you introduced additional constraint that is not present in the base class.