Liskov Substitution Principle

In our last article we learned about the Open Close Principle. In this article we're going to talk about the Liskov Substitution Principle.

The Liskov Substitution Principle, is the third SOLID Principle for OOP.

For those new to SOLID, S.O.L.I.D Stands for:

  • Single Responsibility Principle
  • Open Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

This article is the third of a 5 post series that will cover the SOLID Principles.

Every subclass/derived class should be substitutable for their base/parent class

Continuing our Garden example, Let’s say we have a sub class called Plot that extends Garden. That might look like this:

Class Plot Extends Garden {

    public function quantity(){
    …
        return array($quantity);
    }
}

In our example above, we have overwritten the quantity() method so that it returns an array instead of an integer.

Now if we run the same code we ran in the Single Responsibility Principle Article, we'll notice a problem.

$plants = array(
    'carrots' => new Carrot(5),
    'broccoli'=> new Broccoli(2),
);

$garden = new Plot($plants);
$plotOutput = new GardenOutputter($plot);

echo $gardenOutput->json();  
echo $gardenOutput->html();  

This code returns an E NOTICE on ->html() error. This is because our output formatting class, is assuming the returned value from quantity() is an integer, not an array. So when we convert it to HTML, we're forcing an array into a String, which throws the above error.

To fix this, we need to either not override the quantity() method in our Plot class, or it needs to have the same return type as the Garden class does.

In PHP 7, we can set a return type declaration on a method to define what the response will be.

Class Garden  
{
    public function quantity(): int
    {
        ...
        return $quantity;
    }


}
Class Plots Extends Garden  
{
    public function quantity()
    {
        ...
        return array($quantity);
    }


}

when a sub-type overrides a parent method then the return type of the child must exactly match the parent and may not be omitted.

In the above example, even though we have overridden the quantity() method, and didn't declare a return type, we are still being forced by the Parent class to return an int. Therefore, this code example will return a Fatal Error. Also, we can't change the return type, trying to define the return type in the child class as an array will still throw an error.

By insuring that child classes have the same response types as their parent classes we can follow the Liskov Substitution Principle.

Because now the below code should work just fine, regardless if we pass a Garden class or a Plot Class to our GardenOutputter Class.

$plants = array(
    'carrots' => new Carrot(5),
    'broccoli'=> new Broccoli(2),
);

$garden = new Plot($plants);
$plotOutput = new GardenOutputter($plot);

echo $gardenOutput->json();  
echo $gardenOutput->html();  
comments powered by Disqus