Tuesday, 7 January 2014

Liskov's Principle of Substitution (LSP) and Java Programming

Who is Liskov?

Barbara Liskov (born Barbara Jane Huberman on November 7, 1939 in California) is a computer scientist. She is currently the Ford Professor of Engineering in the MIT School of Engineering's electrical engineering and computer science department and an institute professor at the Massachusetts Institute of Technology.


Statement - 

"In a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may be substituted for objects of type T) without altering any of the desirable properties of that program (correctness, task performed, etc.)."

More formally, the Liskov substitution principle (LSP) is a particular definition of a subtyping relation, called (strong) behavioral subtyping, that was initially introduced by Barbara Liskov in a 1987 conference keynote address entitled Data abstraction and hierarchy.
[from wiki]. Now let us illustrate this - 

I have following structure in the program -
class C1
{
    int a;
    int b;
    void m1(){
       System.out.println("m1 of C1");
    }
    void m2(){
       System.out.println("m2 of C1");
    }
}
class C2 extends C1
{
    int c;
    int d;
    void m3(){
       System.out.println("m3 of C2");
    }
    void m4(){
       System.out.println("m4 of C2");
    }
}
Thats a very common and simple form of inheritance in java.
In the main class I create the objects for these classes
class Main{
  public static void main(String [] args){
    
     C1 obj1 = new C1();
     //
     C2 obj2 = new C2();
  }

C1 --> Base Class.
C2 --> Derived Class.

Inheritance means  : DRY - "Don't Repeat Yourself". 

Rather I established a relationship between C, C1 and C2 by the keyword - "extends".
Notice carefully that there is a great difference between copying & establishing  a relationship.
So basically I prohibit copying when I say "I am inheriting"..which eventually means "I am reusing my/someone else's code". 

Here it means that object of C2 has 8 things but this perception is logical; not physical. Because the members of C1 i.e a, b, m1() and m2() are fetched up by C2 logically and not physically..that means they are available for C2 at runtime. Actually C2 has just 4 things that are written in its own class body. In java, this phenomenon is termed as "extension/mixing". 

So - physically 4 & logically 8 for C2. 
Proper and clear visualization matters a lot in programming. A tiny imperfect visualization of a simple set of code, say a data structure, changes the entire performance of your program . 

In java we have class-based inheritance i.e. here a child object has a copy of  parent's variables.
Now from here onwards in this blog  - the LSP plays.
Lets reconsider the above code with some modification :

class Main{
   public static void main(String [] args){
        C1 obj1 = new C1();
        C2 obj2 = new C2();
        Client1(obj1); //1st call
        Client2(obj2); //2nd call
        Client1(obj2); //3rd call
   }
   static void Client1(C1 h){
        h.m1();
        h.m2();
   }
   static void Client2(C2 q){
        q.m3();
        q.m4();
   }
}


No need to explain about 1st and 2nd call. 
But observe the 3rd  call carefully. Here type is "Parent" and the handle i.e object that is being passed is of type "Child". So the picture is very clear - A child object is behaving as a parent now.

But is it possible? The answer is - YES. 
In fact, we all know and have been using this concept since long. But just to know, this is termed as LISKOV's PRICIPLE OF SUBSTITUTION (LSP). 


"A child object can act as a parent object  & hence, a child object can be passed if parent object is not present. But a parent object can not act as child. So this substitution is asymmetrical.(I can't say vice versa here)". 

To make it clear and simple - A child can act as a substitute to its parent but the other way its not possible. While programming, some people also prefer to refer it as "Liskov's situation".
  • Some key result that I am not explaining here, but you can use and follow are - 
  1. When a child object is playing child's role, method hiding is effective.
  2. When a child object is playing its parent's role, method hiding is ineffective.
  • In programming languages, if you want that a child object should act as a substitute to parent & still it should not loose its own identity(of being child), you must have parents permission.
  • Hence we make such methods "virtual" in C++ and C#. And now this becomes a complete hiding. This complete hiding is nothing but "OVERRIDING"
  • 99% people in the field of programming have wrong concept here.
  • In java, by nature it is overriding.
There are some things, we can't express in C++ & C# but can be in java. In the same way there are some things that are not explainable in java but in C#. In java, by default it is over-riding.
  • NO HIDING IN JAVA.
Some useful links - 
3. c2.com

Thanks a lot. Happy programming.

No comments:

Post a Comment