Understanding Liskov Substitution Principle With Code Examples

The Liskov Substitution Principle is one of the SOLID Principles. In this article, we will learn more about the Liskov Substitution Principle with code examples.

The Liskov Substitution Principle is one of the SOLID Principles. In this article, we will learn more about the Liskov Substitution Principle with code examples.

Object-oriented programming is a programming paradigm that helps software developers write maintainable and scalable software. One of the fundamental principles in object-oriented programming is the Liskov Substitution Principle (LSP) which is also one of the SOLID Principles.

Additional Read: What are SOLID Programming Principles?

PS: This principle was named after computer scientist Barbara Liskov.

What is the Liskov Substitution Principle?

The Liskov Substitution Principle states that objects of a derived class should be able to replace all the objects of the base class without affecting the correctness of the program. In simpler terms, if a class S is a subtype of class T, then an object of class T should be replaceable with an object of class S without introducing bugs into the system.

This principle helps ensure that inheritance hierarchies are designed such that code reusability is promoted. It also reduces the chances of introducing unexpected bugs in the software when using polymorphism.

Why is Liskov Substitution Principle important?

Let's consider an example to understand why the Liskov Substitution Principle is important. We will first see what a violation of LSP looks like.

class Bird{
    public void fly(){
        // Some implementation of flying
    }
}

class Duck extends Bird{

}

// This is a violation of LSP as Ostrich is not the kind of bird that can fly
class Ostrich extends Bird{

}

class Start {
    public static void main(String[] args) {
        Bird bird = new Duck();
        // LSP will break here when we replace Duck with Ostrich
        bird.fly();
    }
}

As you can see in the example above, Ostrich has extended Bird class which violates the Liskov Substitution Principle as it cannot fly. Hence, it cannot replace all the occurences of Bird class.

Now, lets look at an example that adheres to Liskov Substitution Principle

class Bird{
    public void somethingThatAllBirdDo(){
        // Some implementation of flying
    }
}

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

class Duck extends FlyingBird{

}

class Ostrich extends Bird{

}

class Start {
    public static void main(String[] args) {
        Bird bird = new Duck();
        bird.somethingThatAllBirdDo();

        Bird bird2 = new Ostrich();
        bird2.somethingThatAllBirdDo();

        FlyingBird bird2 = new Duck();
        bird2.fly();
    }
}

Conclusion

The Liskov Substitution Principle is a fundamental concept in object-oriented programming that helps ensure that derived classes can be used interchangeably with base classes without causing unexpected issues. Violating LSP can lead to subtle bugs and code that is hard to find out and fix.

To follow LSP, it's essential to design class hierarchies carefully, ensuring that derived classes extend the behaviour of base classes rather than altering them. Wherever there is a situation where a subclass behaves differently from the base class, consider using an adapter or other design patterns to maintain adherence to LSP.

By understanding and applying the Liskov Substitution Principle, you can create more robust and maintainable object-oriented code, leading to better software quality and easier to accommodate enhancements.