SOLID Principles

Example: Bird Hierarchy

Let's consider another example with a bird hierarchy.

Violating LSP

public class Bird
{
    public virtual void Fly()
    {
        Console.WriteLine("Flying");
    }
}

public class Ostrich : Bird
{
    public override void Fly()
    {
        throw new NotSupportedException("Ostriches cannot fly.");
    }
}

In this example, the Ostrich class violates LSP because it cannot perform the Fly method expected of a Bird.

Adhering to LSP

To adhere to LSP, we can introduce an interface for flying birds.


public interface IFlyingBird
{
    void Fly();
}

public class FlyingBird : IFlyingBird
{
    public void Fly()
    {
        Console.WriteLine("Flying");
    }
}

public class Ostrich
{
    // Ostrich does not implement IFlyingBird because it cannot fly.
}

In this refactored design, only birds that can fly implement the IFlyingBird interface. The Ostrich class does not implement IFlyingBird, thus adhering to LSP.

Conclusion

The Liskov Substitution Principle is crucial for designing robust and maintainable object-oriented systems. By ensuring that derived classes adhere to the expectations set by their base classes, you can create systems that are easier to understand, extend, and maintain. In C#, you can achieve this by carefully designing your class hierarchies and using interfaces to define clear contracts for your classes.