## DEV Community is a community of 551,534 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

# A Light Introduction Liskov Substitution Principle

Naomi Dennis ・2 min read

The Liskov substitution principle, is the L in SOLID principles. It was created by Barbara Liskov and states:

Subtypes must be able to substitute base types.

Aside from the obvious implementation of this principle -- ensuring the subtype has the same behavior as the base type -- the implicit implementation is ensuring the subtype has the same semantic behavior as the base type.

Semantic is defined as:

Relating to meaning in language or logic.

And so, we create a definition of what the class name means. Typically, squares and rectangles are defined through their mathematic definition. Mathematically, a square is a shape with four sides in equal lengths. For rectangles, we will be using the definition of a perfect rectangle, meaning a shape where the top and bottom sides have equal lengths and left and right sides have equal lengths.

From this definition, we can conclude that a square's width and height must be the same while a rectangle can have a width different from its height as well as having a width equal to its height.

Let's create classes for these shapes, where we just define the width and height.

We can see that a `Square` object can easily replace a `Rectangle` object in a given situation. All `Square` objects share the same behavior as `Rectangle`.

However, we can see the semantic difference, when we test `#area()`.

Because a rectangle can have a different height than its width the result of `#area()` adheres to our semantic definition.

If we replaced `Rectangle` with `Square` the test will pass, but the `Square` object is no longer behaving the way we expect.

Because a square's width and height cannot be different, the `Square` object breaks our semantic definition. This breaks the Liskov substitute principle.

The easiest way to ensure both `Rectangle` and `Square` pass the test, while satisfying LSP, is to remove line 4.

You may be thinking, why not implement a `#setWidth()` function in `Rectangle` that can be overwritten in `Square`? This would cause `Square` to only share the interface of `Rectangle` instead of its behavior, making the abstraction unnecessary. By removing line 4, we can satisfy LSP and we can go even further by making `width` and `height` private.

### In Conclusion

When implementing inheritance, be sure to adhere to the meaning of the class outside of the implementation. This helps the class become more understandable in the grand scheme of the project.

Another technique that helps ensure classes adhere to LSP is design by contract.