A quick guide to Liskov Substitution Principle with example

Reading Time: 2 minutes


Hi everyone! Today we’re going to discuss about Liskov Substitution principle. It is considered to be the most complicated one among the SOLID principles. This tutorial tries to give a basic understanding of what Liskov substitution is with an example to further explain it in simple terms.

So, the SOLID principles were first introduced by an american software engineer and instructor Robert C. Martin in his 2000 paper Design Principles and Design Patterns. The intent of these five design principles were to make software designs more understandable, flexible, and maintainable. Let’s have a quick look at them –

  • Single responsibility principle – A class should only have one responsibility. There should never be more than one reason to change a class.
  • Open-Closed principle – It simply states that classes should be open for extension but closed for modification.
  • Liskov Substitution principle – Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
  • Interface segregation principle – Many client-specific interfaces are better than one general-purpose interface.
  • Dependency Inversion principle – Depends upon abstractions, not concretions.

Liskov Substitution Principle

The Liskov Substitution principle (LSP) is a particular definition of a sub-typing relation known as behavioural sub-typing. Behavioural sub-typing is basically a stronger notion than typical sub-typing of functions. It is undecidable in general. In a computer program, if S is a sub-type of T, then objects of type S may replace objects of type T. In other words, an object of type T may be substituted with any object of a sub-type S. And they should do this without altering any of the desirable properties of the program (correctness, task performed, etc.). Liskov substitution principle imposes some standard requirements on signatures. Newer object-oriented programming languages are also adapting this approach:

  • Contra-variance of method parameter types in the sub-type.
  • Covariance of method return types in the sub-type.
  • Methods in the sub-type cannot throw new exceptions. Except, if they are sub-types of exceptions thrown by the methods of the super-type.

Now let us try to understand all this further by taking a bad example first and then correcting it with a good one –

Bad Example

public class Bird
    public void fly(){}
public class Duck extends Bird{}

Here, the duck can fly because it is bird. But now, look at this example below –

public class Ostrich extends Bird{}

Now, ostrich is definitely a bird, but it obviously can’t fly. The class Ostrich is a sub-type of class Bird, but it shouldn’t be able to use the fly method which means that we are breaking the Liskov Substitution Principle.

Now let’s take a good example following LSP –

Good Example

public class Bird{}

public class FlyingBirds extends Bird
    public void fly(){}
public class Duck extends FlyingBirds{}

public class Ostrich extends Bird{} 

Finally, to conclude Liskov Substitution Principle, we can say that generally it is an undecidable problem whether any set is the subset of another, i.e. inheritance is generally undecidable.

I hope this article gave you an understanding on what Liskov Substitution principle is and how it is applied. For any queries or suggestion, please feel free to comment. Thanks.

Written by 

Riya is a DevOps Engineer with a passion for new technologies. She is a programmer by heart trying to learn something about everything. On a personal front, she loves traveling, listening to music, and binge-watching web series.