The Liskov Substitution Principle (LSP) is a fundamental concept in object-oriented programming. It states that objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. In other words, subclasses should honor the contracts established by their parent classes.
Consider a base class Bird with a method fly():
class Bird {
void fly() {
System.out.println("Flying");
}
}
class Sparrow extends Bird {
@Override
void fly() {
System.out.println("Sparrow flying");
}
}
Here, the Sparrow class adheres to LSP because it behaves consistently with the base Bird class.
Now, consider a Penguin class:
class Penguin extends Bird {
@Override
void fly() {
throw new UnsupportedOperationException("Penguins can't fly");
}
}
This violates LSP because the subclass Penguin does not adhere to the behavior expected from the Bird class.
To resolve this, use a better abstraction that respects the different capabilities of subclasses:
interface Bird {
void makeSound();
}
interface FlyingBird extends Bird {
void fly();
}
class Sparrow implements FlyingBird {
public void fly() {
System.out.println("Sparrow flying");
}
public void makeSound() {
System.out.println("Chirp chirp");
}
}
class Penguin implements Bird {
public void makeSound() {
System.out.println("Honk honk");
}
}
By adhering to the Liskov Substitution Principle, you ensure that your inheritance hierarchies are robust, predictable, and maintainable, leading to a more reliable software design.