Liskov Substitution Principle
The Liskov Substitution Principle (LSP) states that when you substitute a parent object reference with an object of any of its subclasses, the program should not break.
If a thing looks like a duck and it quacks like a duck, then it better be a duck.
Suppose that your duck has a baby duck. The baby duckling also looks like a duck and quacks like a duck and it also... breathes fire. Whoopsie. That's not supposed to happen.
In this quack analogy, the duck is the parent class. It exhibits duck-like attributes. These duck-like attributes are parts of the duck contract (a duck contract sets up a certain expectation of what a duck class should be like). The duckling is the subclass. Being a descendent of a duck, you expect it to also exhibit duck-like attributes. However, this fire-breathing ability violates the contract because ducks don't breathe fire. This is a violation of the Liskov Substitution Principle.
The LSP doesn't prevent the subclasses from adding new methods. A babyDuck
class can have differing attributes like size = "small"
and color = "yellow"
while the parent class has attributes size = "medium"
and color = "brown"
. These differences won't violate the LSP because they fall within the user expectation. The subclasses don't need to return identical outputs as the parent, but they need to be consistent. A duck subclass with fireBreathing = true
attribute is not consistent because it is not the trait of a duck. It is a duck-dragon chimera.
At the heart of LSP, it's all about having consistent interfaces and following contracts.