Jul 14, 2013

Polymorphism in java - compile time vs run time activity discussed using an use case.

It's very well known concept in OOP and if we have learned any object oriented language we might have learned it in introductory lesson. Here I am documenting some important concepts of Polymorphism which I found useful and informative.
In java language, we have two flavor of polymorphism  :
  • Compile time polymorphism (static binding or method overloading)
     Programs are written in such a way, that flow of control is decided in compile time itself.
     i.e : Using method overloading -  compile time polymorphism is achieved.
    •  Method overloading - An object can have more than one method with same name but different signature (Parameter type and number of parameters different). On compile time compiler ensures that which method (Possibly) will be called at execution time.
      Why "possibly" ? 
      Answer : Because at run time method chosen by compiler may be changed by run time polymorphism. Based on parameter type and number of parameters at compile time compiler ensures that appropriate method will be available at run time but it may change.                
  •  Run time polymorphism (dynamic binding or method overriding)
     Run time polymorphism comes into picture when we use inheritance and there is possibility of parent child relationship in program.
    • Method overriding : Parent class method can be overridden and at execution time it is decided which method will be called based on type of object that initiated this call. During execution JVM starts to look for the candidate method with the signature as exactly defined during the compiling-time. Actually search for the method to be executed starts from the real Object implementation Class (which can be a subclass of the type-Class) and surf the whole hierarchy up.
      what is this real Object implementation class ?
      Answer : Object which initiated the method call not the reference which is pointing to that Object.
    Lets take a use case and discuss the compile time and run time polymorphism.....

    class Gadget {
        public void switchon() {
            System.out.println("Gadget is Switching on!");
        }
    }
    class Smartphone extends Gadget{
        @Override
        public void switchon() {
            System.out.println("Smartphone is switching on!");
        }
    }
    class DemoPersonnel {
        public void demo(Gadget g) {
            System.out.println("Demoing a gadget");
        }
        public void demo(Smartphone s) {
            System.out.println("Demoing a smartphone");
        }
    }

    public class DT {
        public static void main(String[] args) {
            List<Gadget> l = new LinkedList<Gadget>();
            l.add(new Gadget());
            l.add(new Smartphone());
           for (Gadget gadget : l) {
                gadget.switchon();
            }
            DemoPersonnel p = new DemoPersonnel();
            for (Gadget gadget : l) {
                p.demo(gadget);
            }
        }
    }
    -----------------------------------------------------------------------------------------
    On executing this code :
    •  First for loop prints as follows :
               Gadget is Switching on!
               Smartphone is switching on!
    •  Second for loop prints as follows : 
        Demoing a gadget
        Demoing a gadget
     ----------------------------------------------------------------------------------------

    Analysis : 
    In first for loop :

    Ist iteration
    : At compile time gadget.switchon(), since gadget is reference type of Gadget class  so compiler ensure that appropriate method(switchon()) is available in that class.It is important to note that at compile time compiler check for method signature in reference type class and at run time switchon() of gadget class is called because reference is pointing to Gaget class object and displays Gadget is Switching on!.
    2nd Iteration : At compile time same as what is discussed above(since reference is of type Gadget class ), but at run time since reference is pointing to object of Smartphone so JVM will search for switchon() in Smartphone class and displays Smartphone is switching on!.
    In second for loop :  In both iteration at compile time reference type is of
    DemoPersonnel class so compiler ensure that demo(Gadget g) method signature is available and at run time in first iteration demo(Gadget g) is called this is fair enough .But in second iteration also demo(Gadget g) is called why?Answer: Because signature of method which was made available by compiler at compile time same for both iteration so demo(Gadget g) is called for 2nd iteration also.

    Conclusion  :  The whole concept of polymorphism is based on the fact that the concrete class is only known at runtime but not at compile time. This of course means that the compiler must ensure that the methods that are called on a reference will be available on the referenced object at runtime. The only methods for which this holds true are the methods of the class for which the variable was declared (including all inherited methods from the super classes).


    Reference : polymorphism use case

    Cheers !!
    Nikhil
Location: Coimbatore, Tamil Nadu, India