SOLID Principles Illustrated By Examples: 3. Liskov Substitution Principle(LSP)

Manoj Chemate
ILLUMINATION
Published in
3 min readDec 16, 2022

If you haven’t already, check out my previous article on Open Closed Principle.

Liskov Substitution Principle:

Write parent clasess or interfaces in such a way that ALL of it’s derived classes must have valid implementations for ALL parent class methods.

formally, Subtypes must be substitutable for their base types.

Let’s understand it through the example of a Rectangle and a Square,

Since mathematically square is a rectangle you might tend to use an IS-A relationship and override methods,

but this violates LSP since methods in child class are not completely substitutable for parent class methods.

Let’s say a client implements a method that accepts a rectangle and sets height and width and for some weird reason tries to validate the area.

If we pass Square object to this method, but since the setWidth() method changes height as well, the area will be 20*20=400, so even though mathematically square is a rectangle, behavior wise it is not and IS-A relationship is all about behaviour.

Same but still different, isn’t it?

Image by Daniel Reche

If you noticed, there are two issues here

  1. Here author of setAndCheckArea() assumed that setting width does not change the height and it is reasonable to assume so because just looking at the Rectangle class it makes sense, after all, they are two different methods for two different purposes, so Square is really not substitutable to Rectangle here hence it violates LSP.
  2. We can also blame the author of the Square class since method implementations have some code smells, methods in the Square class does something extra than what its name says, but again implementation is right since the code will work fine if tested for all rectangles which are squares.

So what can we do here,

  1. Define pre-conditions that the input object should satisfy before method execution and define post-conditions that the final state of the object should satisfy. We can do this in comments or as part of the method in the parent class. This will help clients to understand the contract of a particular class/interface/function while using it and hence authors of derived classes or client code won’t make any wrong assumptions.

2. Write unit tests for such specific scenarios which can help the author of the client code to understand assumptions.

Some more points to avoid LSP violation:

  1. Revisit your child classes that remove/reduce the functionality of base classes, they are more prone to future errors since children that do less than their base are usually not substitutable for that base, and therefore violate the LSP
  2. Avoid adding more exceptions in derived classes than base classes since users of the base class do not expect them it is not substitutable.
  3. Following LSP enables OCP. Having derived classes/interfaces as perfect substitutes for base classes/interfaces makes them extensible without modification and hence enables OCP.
  4. A violation of LSP is a latent violation of OCP.

that’s it for LSP, let’s take a look at Interface Segregation Principle.

--

--

Manoj Chemate
ILLUMINATION

Software Engineer, I write about my experience with Java, Spring, Micro-services, gRPC, REST, Data Structures, Algorithms, and Software Engineering Interviews.