DEV Community

Erik
Erik

Posted on • Updated on

Liskov Substitution Principle in 3 Minutes

The Liskov Substitution Principle is the L in SOLID object oriented design, and despite having one of the more intimidating sounding names of the 5 principles, it's actually pretty easy to wrap your head around.

It's so simple, in fact, that you're going to understand it in about 3 minutes.

What Is It?

The LSP, in simple terms, states that objects of the same superclass should be able to be swapped with each other without breaking anything.

If we have a Cat and a Dog class derived from an Animal class, any functions using the Animal class should be able to use Cat or Dog and behave normally.

Let's do an example!

Even that definition doesn't quite explain it very well, so let's put it into practice. All will become clear with the code.

In true OOP fashion, let's make an Animal superclass, and a Dog and Cat subclass and capture their favorite kinds of food.

public static class Animal {
  public String favoriteFood;
  public Animal(String favoriteFood) {
    this.favoriteFood = favoriteFood;
  }
}

public static class Dog extends Animal {
  public Dog(String favoriteFood) {
    super(favoriteFood);
  }
}

public static class Cat extends Animal {
  public Cat(String favoriteFood) {
    super(favoriteFood);
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we want to make a method that will let us give these cuties some treats. I don't want to put this method in the Animal classes though, because it's me feeding the animals, not a behavior intrinsic to the animals. Something like Dog.feed might get the point across, but I think feed(Dog) is better, don't you?

Let's make this method and call it GiveTreatTo:

public static void GiveTreatTo(Animal animal) {
  String msg = "You fed the " + animal.getClass().getSimpleName() + " some "  + animal.favoriteFood;
  System.out.println(msg);
}
Enter fullscreen mode Exit fullscreen mode

See here that GiveTreatTo takes any Animal as a parameter. Since our Animal constructors assign the animal's favorite food, we can pretty much count on that data always being there.

This means we don't have to make a method for each animal, i.e., GiveTreatToDog and GiveTreatToCat. Because we implemented LSP, we have one method. Let's see it in action:

public static void main(String[] args) {
  Dog rover = new Dog("bacon");
  Cat bingo = new Cat("fish");

  GiveTreatTo(rover);
  GiveTreatTo(bingo);
}
Enter fullscreen mode Exit fullscreen mode

Now, if we properly implemented the LSP, this program should run just fine. Let's check the output:

You gave the Dog some bacon
You gave the Cat some fish
Enter fullscreen mode Exit fullscreen mode

Amazing. Another benefit of this principal is we can add more and more subclasses of Animal and the GiveTreatTo method won't need any tinkering.

Wrap Up

Pretty non-intimidating right? As with many things in programming and computer science, the name belies its simplicity. Now, go out there and make your subclasses swappable, and thank Dr. Barbara Liskov for such a useful principle.

Top comments (9)

Collapse
 
pareshjoshi profile image
Paresh

Can you expand your example that breaks LSP? I guess, that way entry level programmers will be able compare it.

Collapse
 
danielrusnok profile image
Daniel Rusnok • Edited

Nice example of violation the LSP could be to make an animal purr. Everybody knows that only one who can purr in our domain are cats, that is why method Purr could not be in Animal class. Dog dont purr, dogs cant inherit such a behavior.

Collapse
 
pareshjoshi profile image
Paresh

That makes perfect sense!

Collapse
 
swarupkm profile image
Swarup Kumar Mahapatra

LSP also makes sure thatOpen Close principal is followed

Collapse
 
sketchydev profile image
Shane Booth

Although the two are related and support each other, it is possible to violate either of them while maintaining the other - have a look here softwareengineering.stackexchange.... for a worked example

Collapse
 
swarupkm profile image
Swarup Kumar Mahapatra

Thanks Shane.

That was a super big explanation and a helpful one.

Collapse
 
schwarzwald profile image
schwarzwald • Edited

I think this is more an example of the strategy pattern than the LSP. If I understand it correctly LSP is about not breaking the contract of superclass with the implementation of subclass.

Collapse
 
erikwhiting88 profile image
Erik

You're right. I would argue, though, that the strategy pattern adheres to the Liskov Substitution Principle and is thus a good example for conceptualizing the principle, especially quickly

Collapse
 
augustas profile image
Augustas

Helpful! Thanks!