SOLID Principles Made Ridiculously Simple: Liskov Substitution Principle

We talk about the Liskov Substitution Principle (LSP) today. If you haven’t checked out the previous blog posts on the Single Responsibility Principle or the Open Close Principle, make sure to check them out before reading on!

As usual, the definition of the LSP is as follows: If S is a subtype of T, then objects of type T may be replaced with objects of type S. Sounds like common sense, duh? Or does it sound too cryptic to understand?

In platypus language, we interpret the LSP as such:

When inheriting, the child should not change the behaviour that it inherits from the parent.”

Let’s dive into a simple platypus example so we can be clear of what kind of code violates LSP.

class Mammals {
    public void childBirth() {
        giveBirthLive();
    }
}

class Platypus extends Mammals {
    @Override
    public void childBirth() {
        layEggs();
    }
}

Why is this a violation, you might ask? Well, in some cases, when we call the childBirth() method, we expect the mammal to give birth to a live baby. However, Platypus (which is the child class that inherits from mammals in this case) will behave differently and start to lay eggs! We can’t have unpredictable behaviour from Mammals, right?

Imagine the zoo starts preparing for all the Mammals for their child births. None of them would be prepared to take care of eggs, because they cannot predict that a mammal can lay eggs!

Perry lays an egg!

You would probably have another question. If the child can’t have new behaviours, then why would anyone consider inheritance?

The answer is simple. LSP encourages us to add on new behaviour to existing ones, and try to leave as much of the existing behaviour unmodified as possible.

Counter Intuitive

LSP goes against the law of nature which we are familiar with. In mathematics, we learn that a square is a rectangle, because it is a special type of rectangle. But try having Square objects extend from Rectangle objects, and you can probably see why it is not a good idea.

How to follow the Liskov Substitution Principle

  1. Ensure that if we substitute the parent class with the child class, things don’t break! This also reminds us why we should always design the child class to have additional behaviours instead of changing behaviours.
  2. If substitution doesn’t fit the problem you’re trying to solve, then maybe try composition? That is, let your new class contain the original class, then act like a wrapper to interpret (or re-interpret) the behaviour of the original class that is being contained.

Have fun!