The Liskov Substitution Principle (LSP) is one of the SOLID principles of object-oriented programming. It states:
“Objects of a superclass should be replaceable with objects of its subclasses without altering the correctness of the program.”
In simpler terms, if a class A
is a parent class, and B
is a subclass of A
, you should be able to use B
objects wherever A
objects are expected, and the program should still work correctly.
Example: Understanding LSP with Birds
Imagine you have a class Bird
with a method fly()
. All birds are supposed to fly, so the method is included in the base class:
class Bird: def fly(self): print("Flying!")
Now, you create subclasses:
- Sparrow: Sparrows can fly, so everything works fine:pythonKopiraj kod
class Sparrow(Bird): pass # No changes needed
2.Penguin: Penguins are birds, but they cannot fly. If you implement Penguin
like this:
class Penguin(Bird): def fly(self): raise NotImplementedError("Penguins cannot fly!")
You are violating LSP because if the program expects a Bird
and gets a Penguin
, it will break when fly()
is called.
Why Does This Violate LSP?
The substitution principle says that subclasses must fulfill the expectations set by their parent class. In this case, the Bird
class promises that every bird can fly. However, a Penguin
does not meet that expectation.
Solution: Follow LSP
To fix this, you can rethink your design. Instead of assuming all birds can fly, separate flying behavior into its own abstraction:
from abc import ABC, abstractmethod class Bird(ABC): @abstractmethod def describe(self): pass class FlyingBird(Bird): @abstractmethod def fly(self): pass class Sparrow(FlyingBird): def describe(self): return "I am a sparrow." def fly(self): print("Flying high!") class Penguin(Bird): def describe(self): return "I am a penguin. I cannot fly, but I swim well!"
Here’s why this works:
Bird
now only defines common behavior for all birds, such asdescribe()
.FlyingBird
adds behavior specific to birds that can fly.- A
Penguin
only implementsBird
, while aSparrow
implements bothBird
andFlyingBird
.
Key Takeaway
The Liskov Substitution Principle ensures that:
- Subclasses behave in a way that respects the expectations of their parent class.
- Your program doesn’t break when you replace a superclass object with a subclass object.
By adhering to LSP, your code becomes more robust and easier to maintain.