Monday, January 23, 2012

Liskov Substitution Principle, a simple example

The Liskov Substitution Principle of object oriented design states:

In class hierarchies, it should be possible to treat a specialized object as if it were a base class object.


using System;

namespace Liskov
{
 class Rectangle
 {    
  int _height;
  public virtual int Height
  {
   get{
    return _height;
   }
   set {
    _height = value;
   }
  }
  
  int _width;
  public virtual int Width
  {
   get {
    return _width;
   }
   set {
    _width = value;
   }   
  }
  
  public int Area
  {
   get {
    return _width * _height;
   }
  }
  
  
  public Rectangle (int width, int height)
  {
   Height = height;
   Width = width;
  }
  
 }
 
 
 class Square : Rectangle
 {
  public override int Height {
   set {
    base.Height = value;
    base.Width = value;
   }
  }
  
  public override int Width {
   set {
    base.Width = value;
    base.Height = value;
   }
  }
  

  public Square (int side) : base(width: side, height: side)
  {
  }
  
 }
 
 class MainClass
 {
  public static void Main (string[] args)
  {
   Rectangle s = new Square(side: 10);
   
   // 100, correct
   Console.WriteLine ("Area: {0}", s.Area); 
   
   // reusing the object r as rectangle object     
   s.Height = 4; 
   s.Width = 3;
   
   // expecting 12, actual output is 9. incorrect. Liskov Substitution Principle is violated
   Console.WriteLine ("Area: {0}", s.Area); 
  }
 }
}

The code above violates Liskov Substitution Principle, there should be no side effects on results even I use Square object for Rectangle purposes. Don't override properties just because it look smart to do so.

To set the Square's sides properly, set the two sides via one property only:

public int Side {
 get {
  return Height;
 }
 set {
  Height = Width = value;
 }
}



No comments:

Post a Comment