Do abstract properties violate the Liskov substitution principle?
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() { retur开发者_JAVA百科n 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.).
In this case, users of those classes will probably write:
...
if (pet.getsSpecialTreatment()) {
// special treatment
...
} else {
// normal treatment
...
}
...
This code will work on both cases, so you would not be violating LSP. However, if you had
public class UnknownAnimal extends Pet {
@Override public boolean getsSpecialTreatment() {
throw new UnsupportedOperationException("Unknown species");
}
}
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.
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.
精彩评论