Liskov Substitution Principle (LSP)

Liskov Substitution Principle (LSP)

Liskov Substitution Principle (LSP) states that objects of a base class should be replaceable by objects of a derived class without altering the correctness of the program.

In other words, derived classes must behave in such a way that they can stand in for their base classes without breaking the program.

 

Key Principles

  • A subclass must not break the behavior expected from the base class.
  • Derived classes should extend behavior, not override it with contradictory logic.
  • No side effects or errors should occur when using a subclass in place of a base class.
  • Method contracts (preconditions and postconditions) should be maintained or strengthened.
  • LSP promotes safe polymorphism — you should be able to use a subclass object wherever a base class object is expected.

 

LSP Violation Example

class Rectangle

{

    public virtual int Width { get; set; }

    public virtual int Height { get; set; }

 

    public int GetArea() => Width * Height;

}

 

class Square : Rectangle

{

    public override int Width

    {

        set { base.Width = base.Height = value; }

    }

 

    public override int Height

    {

        set { base.Width = base.Height = value; }

    }

}

Usage:

Rectangle rect = new Square();

rect.Width = 5;

rect.Height = 10;

Console.WriteLine(rect.GetArea()); // Outputs 100 instead of expected 50

This violates LSP because Square overrides behavior in a way that contradicts what the base class Rectangle promises.

 

Fix Using Composition Instead of Inheritance

abstract class Shape

{

    public abstract int GetArea();

}

 

class Rectangle : Shape

{

    public int Width { get; set; }

    public int Height { get; set; }

 

    public override int GetArea() => Width * Height;

}

 

class Square : Shape

{

    public int Side { get; set; }

 

    public override int GetArea() => Side * Side;

}

Each class now has its own specific logic and behavior. LSP is respected, and substitution will not cause unexpected behavior.

 

Interview Q&A Format

Q1: What is the Liskov Substitution Principle?
A: It ensures that a subclass can replace its base class without breaking the program’s behavior.

Q2: What are the key rules of LSP?

  • Subclass should not override methods in a way that contradicts base class expectations.
  • Subclass must maintain method contracts (preconditions and postconditions).
  • Avoid unexpected exceptions in derived classes.
  • Subclasses should not require extra conditions to work.

Q3: How do you identify an LSP violation?

  • The program breaks when using a subclass where a base class was expected.
  • Subclass introduces new validations or changes output format.
  • Unexpected results or errors occur during substitution.

Q4: How can you fix LSP violations?

  • Refactor the class hierarchy.
  • Replace inheritance with composition where appropriate.
  • Use interfaces to segregate behavior (e.g., IFlyable, IWalkable).
  • Ensure that overridden methods follow the expected contract.

 

Real-Life Analogy

Example:
A Bird class has a Fly() method. But an Ostrich (a bird) can't fly.

class Bird { public virtual void Fly() { } }

class Ostrich : Bird { public override void Fly() => throw new NotSupportedException(); }

This breaks LSP because Ostrich doesn't conform to the behavior expected from Bird.

Fix: Split into separate interfaces for FlyableBird and NonFlyableBird.

 

Summary

LSP ensures that derived classes can be used in place of base classes without changing program behavior. It is a key part of writing maintainable and extendable object-oriented systems.

When you follow LSP:

  • Behavior remains predictable.
  • Code is more reusable.
  • Bugs due to unexpected subclass behavior are minimized.

 

Comments

Popular posts from this blog

Promises in Angular

Mastering Your Angular Workflow: Essential CLI Commands for Efficient Development

Observables in Angular