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.).
In short, yes. The LSP applies to essentially all public inheritance. The fact that a base class is abstract doesn't change that.
A very common violation of this principle is the partial implementation of interfaces or base class functionality, leaving unimplemented methods or properties to throw an exception (e.g. NotImplementedException).
A good example here is that of a bird and a penguin; I will call this dove-penguin problem. The below is a Java code snippet showing an example that violates the LSP principle. Here, the Dove can fly because it is a Bird. In this inheritance, much as technically a penguin is a bird, penguins do not fly.
The Open/Closed Principle To understand the Liskov Substitution Principle, we must first understand the Open/Closed Principle (the “O” from SOLID). The goal of the Open/Closed principle encourages us to design our software so we add new features only by adding new code.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With