Liskov Substitution Principle - SOLID

Posted on

A Brief Explanation

The Leskov Principle states that all the methods from classes than inherit from the same Interface must return the same type. Put another way if i have an interface that states that all classes that implement this interface must have a method called get(). For each one of these get() methods the same type must be returned. If it is an array for one, it must be an array for all.

The idea being that i should be able to substitute the class that i am using in my code, and i should be left with the same return type.

In Practice

The best way to demonstrate this is by breaking this rule.

interface LessonRepositoryInterface {
    /**
    * every class that extends this interface
    * must have a method called getAll()
    *  AND all must return the same type
    **/
    public function getAll();   
}

/**
* Lets say we want to get lessons
**/
class FileLessonRepository {
    public function getAll() {
        return []; //This returns and array
    }
}

class DBLessonRepository {
    public function getAll() {
        return DBLesson::all(); // This returns a Laravel collection object
    }
}

The Liskov Principle states that we must be able to switch these two classes around and we should receive the same type. We have just broken this rule, one returns an array, and the other a collection object.

$lessons = LessonDBRepository->getAll();

foreach ($lessons as $lesson) {
  // do something with $lesson
}
$lessons = LessonFileRepository->getAll();
//Breaks here as we do not have an array but a collection
foreach (DBFileRepository as $item) {
  // do something with $item
}

To finish You should be able to call ->getAll() on both LessonFileRepository and LessonDBRepository since they both use the same interface and they should both return they same type.