SOLID Design Principles

0% completed

Previous
Next
Using Composition to Follow Liskov Substitution Principle (LSP)

In the previous lesson, we explored how using inheritance can sometimes violate the Liskov Substitution Principle. Another way to follow LSP without falling into the pitfalls of inheritance is by using composition over inheritance. This method allows you to design systems that are more flexible and avoid situations where subclasses cannot properly fulfill the parent class's contract.

Example: Bird and Flying Behavior

Let’s use the example of birds. If we use inheritance, we might create a Bird class that defines general bird behaviors, like flying. However, some birds—like penguins—cannot fly.

Inheritance forces subclasses to implement or override behaviors they don’t need, which can lead to LSP violations.

Problem with Inheritance (Violating LSP)

Python3
Python3
. . . .

Here, the Penguin class is forced to inherit the fly() method from the Bird class, even though penguins can’t fly. This violates LSP because substituting a Penguin for a Bird causes the program to break when fly() is called.

Solution: Using Composition to Follow LSP

To avoid this issue, we can use composition. Instead of forcing birds to inherit flying behavior, we can create a separate Flyable interface and only assign flying abilities to birds that can actually fly.

Step 1: Create Interfaces for Flyable and Non-Flyable Birds

Python3
Python3
. . . .

Step 2: Implement Bird Classes with Composition

We now separate the flying ability from the bird itself. Birds that can fly will implement the Flyable interface, while birds that can’t fly won’t inherit unnecessary behavior.

Python3
Python3
. . . .

In this solution, we use composition by creating a Flyable interface. Now, birds that can fly, like sparrows, implement the Flyable interface, while penguins do not. This keeps the hierarchy clean and avoids forcing subclasses to override or implement unnecessary behavior.

Step 3: Test the Composition-Based Design

Python3
Python3
. . . .

How Composition Solves LSP

With composition:

  • No Unnecessary Methods: Birds that can’t fly (like penguins) aren’t forced to implement or override the fly() method, avoiding LSP violations.
  • Flexible Design: You can easily add other behaviors to birds (such as swimming) without affecting birds that don’t need that behavior.
  • Follows LSP: You can substitute Sparrow for Bird without worrying about breaking the program, as fly() is only available to birds that can actually fly.
Python3
Python3

. . . .

Using composition over inheritance allows us to avoid violating the Liskov Substitution Principle. By separating specific behaviors like flying into an interface, we avoid forcing all bird subclasses to implement or override methods that don’t apply to them. This creates a more flexible, maintainable design that follows LSP and allows each class to behave according to its own characteristics.

.....

.....

.....

Like the course? Get enrolled and start learning!
Previous
Next