Object-oriented languages help us reuse code with inheritance. This way we can write less code and get the same result. So should we inherit a class from the base class, once we encounter similarities in them? In this topic, we'll show you in broad strokes the principle that guides us to do it wisely.
Liskov Substitution Principle (LSP)
Assume that you're working in chemical production and control the components of a washing powder. You start with a superclass WASHING_POWDER that has a method WASH_CLOTHES. As an experiment, the company creates two structures of powder and releases them under the names CLEANY and SHINY.
Within a week, your company starts getting calls from angry customers: every time they wash clothes with SHINY, it bleaches them. You start analyzing the components and find out that SHINY has a similar structure to bleach. You realize that apart from the base class one of the subclasses behaves differently, and it's odd for everyone who tries to use it.
Although it's only an imaginary situation, it can happen with your code too. To prevent disasters like this, follow the rule: any subclass S of the base class C can substitute C without changing the correctness of the program. This rule is widely known as the Liskov Substitution Principle or LSP.
Degenerate Methods
Next day a new idea comes to your mind, and you create two methods to distinguish these products: SHOW_POWDER_PROPERTIES and SHOW_BLEACH_PROPERTIES. Each method prints right on the box what you can and cannot do with a product.
To your surprise, customers still get confused because they don't understand, why does a company sell a powder that cannot do something they need. "CLEANY cannot bleach, so why do you print this ridiculous warning?" - they say.
Sometimes these methods are useless and annoying, other times they are degenerate, i.e. don't do anything at all. The main purpose of SHINY as a WASHING_POWDER is degenerate, we cannot wash clothes with it.
Problem resolution
Not to confuse anybody further, you decide to create a new superclass BLEACH and make the SHINY a subclass of it.
This time all the customers are happy because the labels on the boxes are just right. They can easily pick what they want to buy because they know what to expect from a purchase.
This tale is, of course, a metaphor for programming. To create software, you often collaborate with other developers and write code that they will use. If your subtypes behave unpredictably, the result of the whole program becomes unexpected. Though it takes time to decide when and what to inherit from a base class, it will definitely save you time in the future.
Conclusion
In this topic, we've gotten to know the Liskov Substitution Principle and taken a few important notes about it:
-
we should create subtypes that behave like their base types,
-
we should avoid useless and degenerate methods,
-
sometimes it's better to create a new base class and inherit a class from it.