To become a senior among millions of programmers!
This is the 3rd article in the series “SOLID for young people hard coding.” In this article, I will talk about the Liskov Substitution Principle (LSP)
- Single Responsibility Principle
- Open / Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
In a program, objects of a subclass can replace the parent class without changing the correctness of the program
Explain the principle
A little warning, this principle is a bit abstract and difficult to understand, so I will try to explain it as simply as possible. If you don’t understand it for the first time, try to read it carefully a few times; if you still don’t understand … please google to find another article.
To maintain the correctness of the program, the subclass must replace the parent class. Easy to understand, say this: Once upon a time, you must have had an Individual Portable Brick Game. At that time, every time the battery ran out, I asked a few thousand to go out and buy the battery to play it again. When I ran out of batteries and had no money, I went to pick up some piggy bank batteries attached to it and play it temporarily. Unexpectedly after inserting the battery, just turned on the device gleefully, the device was burned because the battery voltage was more than normal. That was all the way to the machine just because … sorry, money to buy batteries.
I will give 2 common examples of LSP violations:
1. The subclass throws an exception when calling the function
Suppose we want to write a program to describe flying birds. Eagles, sparrows, and ducks fly, but penguins cannot fly. Since penguins are also birds, I let them inherit the Bird class. However, because penguins cannot fly, when we call the penguin’s flight function, we will throw NoFlyException.
We create an array containing the birds and then iterate over the elements. When calling the Fly function of Penguin class, this function will throw an error. The Penguin class caused a runtime error, unable to replace its parent class Bird, which violated the LSP.
2. The child class changes the parent class behavior
This is the classic example of squares and rectangles that people often use to explain LSP; I just write and explain a little.
First, let’s read the code below. We have 2 classes for square and rectangle. Everyone knows a square is a rectangle with 2 equal sides, so we can let the Square class inherit the Rectangle class to reuse the code.
Because a square has 2 equal sides, each time we set the length of one side, we always set the other side's length. However, on a test run, this action changed the Rectangle class's behavior, resulting in LSP violation.
The result is 5 x 5. If it is true, it must be 10 × 5 because the area of a rectangle is length x width
Class Square changes the behavior of the parent class Rectangle, set both length and width to 5
In this case, for the code to not violate the LSP, we must create a parent class, the Shape class, then let Square and Rectangle inherit this Shape class.
This is the most easily violated… principle; the main reason is inexperience in class design. Usually, the classes' design is based on real-life: the square is the rectangle, the penguin is the bird. However, this relationship cannot be verbalized in code. Remember 1 thing:
In life, A is B (the square is a rectangle; the penguin is a bird) does not mean that class A should inherit class B. Only let class A inherit class B when class A can replace class B.
The pig battery is a battery but cannot replace the battery, the penguin is a bird but cannot replace it, so these 2 examples violate the LSP.
This principle hides in almost every piece of code, making the code flexible and stable without our knowledge. For example, in C #, we can run the foreach function with List, ArrayList, LinkedList because they all inherit the IEnumerable interface. Class List, ArrayList, .. have been designed correctly in LSP; they can replace IEnumerable without damaging the program's correctness.
What is object-oriented design? What is it all about? What it's benefiting? What are its costs? It may seem silly to…