From Wikipedia,
Liskov's notion of a behavioral subtype defines a notion of substitutability for objects; that is, if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program (e.g. correctness).
Suppose the following class hierarchy:
- The base abstract class -
AnimalWithFur
. It has a read-only propertyfurColor
that is overridden in successors. - Base class's successor -
Cat
, which overridesfurColor
and returns gray. - Cat's successor -
Tiger
, which overridesfurColor
and returns striped.
Then we declare a method with an argument of type Cat
(not AnimalWithFur
).
Is sending a Tiger
instance to that method a violation of the L in SOLID?
Strictly speaking, yes. The wiki article summation of Liskov says:
If you go back to the original paper by Barbara Liskov, it's literally stricter in its wording, 3.3. Type Hierarchy:
(Empahsis mine)
So if you replace an instance of
Cat
with another instance that does something different, i.e. returning stripped not grey, then that is a Liskov violation in the original sense, because a program could be easily defined that relies on the color being grey, here:The behaviour of that program will change if you pass it a
Tiger
in place of aCat
.However, in the normal way LSP is applied, it is not a violation if you did not add extra preconditions or postconditions. This is a more practical, less academic definition as people accept that when replacing an instance of one concrete type with another you do intend to change the behaviour of the program while maintaining desirable properties of that program. So presuming the client code can handle stripped like any other colour, and grey was not required for a "desirable" property of the program then it does not violate.