Understanding SOLID in C++ : Liskov Substitution principle
Source : Google

Understanding SOLID in C++ : Liskov Substitution principle

This is the 3rd part of the series “Understanding SOLID in C++”. In this article, we will talk about the “L” in SOLID i.e.?Liskov Substitution Principle.

In this series, we have already discussed about the?Single Responsibility Principle and Open-Closed Principle. If you have not gone through this, you can see from the below


Liskov Substitution Principle

Liskov Substitution Principle states that “Objects of superclass can be should be replaceable with objects of subclass without altering the correctness of program.

In Simple terms, it means that a subclass should be able to be used wherever superclass is expected, and it should introduce the error or break the program.

In another words, You are expected that you should not reduce the number of functionality in the subclass than superclass.

Lets take an example to understand the above with a Flying Bird Example.

Flying Bird?Example

Suppose we have to design a bird hierarchy in which we need to implement birds like Penguin, Crow, etc.

class Bird {
    public:
        virtual void fly() = 0;
};

class Crow : public Bird {
    public:
        void fly() override {
            cout << "Crow is flying" << endl;
        }
};

class Penguin : public Bird {
    public:
        void fly() override {
            throw runtime_error("Penguins can't fly");
        }
};        

In the above example, we have a class called Bird which is a abstract class having a pure virtual function called fly()?

We also have two subclasses Crow and Penguin that is inheriting Bird class. Since Penguins can’t fly the method fly() is throwing runtime_error.?

Problem in above?approach

Now let’s say we have a function that takes a Bird object and calls its fly() function.

void makeBirdFly(const Bird& bird) {
    bird.fly();
}        

If we call this method with Crow object, it will work as expected but if we call this method with Penguin object, it will throw a run time error. This violates the Liskov Substitution Principle because substituting an Penguin for a Bird results in unexpected behavior.

Here we are also reducing one functionality from the subclass Penguin.

There are many disadvantage if we don’t follow this principle

  • It will be very difficult to maintain the hierarchies between class. Lot of run time issues and strange behavior might happen.
  • Unit tests of the superclass will never be passed for the subclass. This will make code difficult to test.
  • There might be lot of conditional checking that you need to put on code. That might become overhead to the system.

Solution to?above

To fix this violation, we can use more appropriate hierarchy.

We can have a intermediate superclass called FlyingBird that represents the birds that can fly.?

class Bird {
    public:
        virtual bool canFly() = 0;
};

class FlyingBird {
    public:
        bool canFly() override {
            return true;
        }
        virtual void fly() = 0;
};

class Crow : public FlyingBird {
    public:
        void fly() override {
            cout << "Crow is flying" << endl;
        }
};

class Penguin : public Bird {
    public:
        void canFly() override {
            return false;
        }
};        

Now let’s update our makeBirdFly() function to use this new hierarchy.

void makeBirdFly(const FlyingBird& bird) {
    bird.fly();
}        

Now, if we call makeBirdFly() with Crow object, it will work as expected. If we try to call it with Penguin object, it will give us Compile time error since Penguin does not inherit from FlyingBird.

This ensures that only a bird that can fly can be passed to makeBirdFly() function, which prevents from giving unexpected behavior, which maintains the Liskov Substitution Principle.

No alt text provided for this image
Source : Google

It is always recommended keeping your base Abstractions as simple and minimal as possible, making it easy to extend by the subclasses.

I hope we have understand the third principle of SOLID i.e. Liskov Substitution Principle using the examples in C++.

We will go through the remaining principles in our next article. Hope you learned somethings through this. See you in next article.?

We will cover the remaining principles in upcoming articles. We hope that you found the information provided thus far to be informative and valuable. Thank you for reading and we look forward to seeing you in the next article.

Subscribe to my newsletter for upcoming articles. I am targeting to cover low level design topics with case studies and the implementation and examples will be in C++.

Happy Coding!?

TIP: Implement these principles in C++ with some examples, its very easy to understand the applications.

#design?#lowleveldesign?#softwareengineering?#lld?#hld?#designpatterns?#designprinciples?#solid?#interviewprep?#interview?#interviewpreparation

Robert Casey

Senior Principal Engineer Embedded Software at Northrop Grumman

1 年

Hi Abhishek, Excellent example - thank you! I plan to share this with my team. I did have one question though, regarding your solution. Shouldn't the declaration for FlyingBird be: class FlyingBird : public Bird Otherwise, it is not clear what the canFly function is overriding from a base class, right? Thanks! -Robert

Shilpa Dogra

MS, BE |Professional Project Management by Google |CSM | Ex-Graphics Senior Engineer at Stryker R&D | Visualisation 3D & 2D | C++ | Medical devices

1 年

Hello Abhishek, well written though this "In Simple terms, it means that a subclass should be able to be used wherever superclass is expected, and it should introduce the error or break the program." seams not right I think It should not introduce any error.

回复
KOUSHIK NAG

SWE @ISRO??| NavIC | Striker@ISRO Football Team

1 年

True ! using instancof checks to invoke a function on inherited objects is dreadful at times !

KRISHNAN N NARAYANAN

Sales Associate at American Airlines

1 年

Thanks for sharing

Kartik S.

SDE @Amazon | GSoC @RedHat | Open Source and Coding Mentor |Ex @Nagarro|Ex @Coding Blocks|System Design Content Creator|20k+ linkedin followers|3 million views|open for collaborations

1 年

????

要查看或添加评论,请登录

社区洞察

其他会员也浏览了