0% completed
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.
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.
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.
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.
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.
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.
With composition:
fly()
method, avoiding LSP violations.Sparrow
for Bird
without worrying about breaking the program, as fly()
is only available to birds that can actually fly.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.
.....
.....
.....