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
Post a Comment