What Is The Liskov Substitution Principle?


2 min read

The Principle Definition

Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T.

That’s great, but what does it mean 🤷🏽‍♀️? In simpler terms, a child class should be able to substitute a parent class, without any unexpected behaviour. It ensures inheritance is being used correctly.


An example of adhering to the Liskov Substitution Principle

Below is the class Animal. When the speak method is called, a string is expected to be returned. The method does not have any parameters.

1class Animal
2 def speak
3 ""
4 end
5end

Below are subclasses Cat and Dog. Both inherit from Animal and have a speak method.

1class Cat < Animal
2 def speak
3 "Meow!"
4 end
5end
6
7class Dog < Animal
8 def speak
9 "Woof!"
10 end
11end
12
13
14cat = Cat.new
15dog = Dog.new
16
17cat.speak # "Meow!"
18dog.speak # "Woof!"

Although calling the speak method on Cat returns 'Meow!' and 'Woof!' for Dog, a string is returned in both cases. In addition, no arguments are required. As a result, instances of these subclasses can be substituted where an instance of Animal is used.


Violation of the Liskov Substitution Principle

Below is the class Jellyfish, which is a subclass of Animal. Its speak method has a parameter name and returns a string.

Although this method returns a string, it needs a name as an argument when called. As the parent class’ speak method doesn’t require a name argument, an instance of the Animal class cannot be substituted with an instance of the Jellyfish class.

1class Jellyfish < Animal
2 def speak(name)
3 "#{name} cannot speak"
4 end
5end
6
7jellyfish = Jellyfish.new
8jellyfish.speak("Jelly") # "Jelly cannot speak"

In addition, if the speak method of a subclass returned anything other than a string, this would also violate the principle.


In conclusion

To adhere to the Liskov Substitute Principle, a child class should be able to substitute a parent class, without any unexpected behaviour. This is to ensure inheritance is being used correctly.


Helpful resources

Previous post:
What Is The Dependency Inversion Principle?
Next post:
What Are Interfaces, Abstract And Concrete Classes?

Discussion