Liskov Substitution Principle
Definition 2: Functions
that use references to base classes must be able to use objects of derived
classes without knowing it.
Definition 2:
Object inheriting from base class or interface or other abstraction must be
semantically substitutable for the original abstraction.
Definition 3: If
a program module is using a Base Class, then the reference to the base class
can be replaced with a derived class without affecting the functionality of the
program module.
Problem
We
all know that square is a rectangle from geometry. Now create a Rectangle base
class with associated Height and Width properties and create Area() method to
calculate the area in Rectangle base class.
public class Rectangle
{
public virtual int Height { get; set; }
public virtual int Width { get; set; }
public int Area()
{
return Height * Width;
}
}
Now
create a Square class derived from Rectangle base class.
public class Square : Rectangle
{
public override int Height
{
get
{
return base.Height;
}
set
{
base.Height = value;
base.Width = value;
}
}
public override int Width
{
get
{
return base.Width;
}
set
{
base.Width = value;
base.Height = value;
}
}
}
Now
create instance of a Rectangle class, set Height and Width as show below and
call current instance Area() method to calculate the area.
Rectangle rectangle1 = new Rectangle();
rectangle1.Height
= 5;
rectangle1.Width
= 4;
Console.WriteLine("
Area of rectangle is " +
rectangle1.Area());
The
calculated area returned by “rectangle1” instance is 20. This is correct as
since area of rectangle is 5 * 4 (Height * Width).
Now
we know that Square is also a Rectangle. Create a square instance and assign it
to Rectangle variable and set Height and Width as shown below.
Rectangle rectangle2 = new Square();
rectangle2.Height
= 5;
rectangle2.Width
= 4;
Console.WriteLine(" Area of rectangle is " + rectangle2.Area());
Now if we call Area() method from “rectangle2”, the returned
area value is 16. But we are expecting 20 as 5 * 4 = 20.
This is not breaking any functionality but the above
design is not giving the desired result. This kind of problem is known as
violation of Liskov’s substitution principle.
The solution for this problem is to identify the suitable
abstraction. If we fail do then we will end up with above mentioned violations.
Solution
Identify the proper abstraction. In
this case we can create a new interface as IShape which contains only Area()
method.
public interface IShape
{
double Area();
}
Now create a Rectangle and Square
class derived from IShape interface.
public class Rectangle : IShape
{
public int Height { get; set; }
public int Width { get; set; }
public double Area()
{
return Height * Width;
}
}
public class Square : IShape
{
public int width { get; set; }
public double Area()
{
return width * width;
}
}
Rectangle rectangle1 = new Rectangle();
rectangle1.Height
= 5;
rectangle1.Width
= 4;
Console.WriteLine("
Area of rectangle is " +
rectangle1.Area());
The
returned rectangle area is 20.
Square square = new Square();
square.Width
= 4;
Console.WriteLine("
Area of rectangle is " + square.Area());
The
returned square area is 16.
By using the same IShape interface we
can extend this to calculate the area of Circle, Eclipse etc. by creating their
respective classes and without modifying the existing code.
Comments
Post a Comment