The Liskov Substitution Principle (LSP) states that if a program is using a base class, it should be able to use any of its subclasses without the program knowing it. In other words, the subclasses should be substitutable for their base class.
A `Bird` class has a method `Fly`. The `Penguin` class inherits from the `Bird` class but throws an exception in the `Fly` method because penguins cannot fly. This violates LSP because we cannot use `Penguin` wherever we use `Bird`.
class Bird {
public virtual void Fly() {
// Default implementation.
}
}
class Penguin : Bird {
public override void Fly() {
throw new NotSupportedException("Penguins can't fly.");
}
}
A better design would be to have a separate `FlyingBird` class that inherits from `Bird`. Now, the `Penguin` class can inherit from `Bird` without violating the LSP.
class Bird {
// Other bird-related methods.
}
class FlyingBird : Bird {
public virtual void Fly() {
// Default implementation.
}
}
class Penguin : Bird {
// Penguin-specific methods.
}