Thursday, 21 February 2013

POLYMORPHISM


One interface multiple methods. i.e one interface is used for different actions
There are two types of polymorphism:

   1)     Compile time polymorphism – function overloading
   2)     runtime polymorphism—dynamic linking

For example : if in a program  we have 3 different types of stacks:
One which calculates int, double and other float..
Then we can have a method named stack (same name) with different types of parameters.(different actions):
  -->stack(int)
  -->Stack(double)
  --->Stack(float)
i.e same name but different type of arguments.

The compilers’s job is to select the right method, programmer doesn't have to select it manually.
But how does Compiler know?? which method to select at compile time?

FUNCTION OVERLOAD RESOLUTION IN JAVA

Java's overload resolution process operates in two phases.

The first phase: For a given function call, find the set of all applicable methods on the basis that there must exist either an exact match or a widening type conversion from each argument in the function call (i.e the actual parameters )to the corresponding parameter of the method being considered. If this set consists of only one method, select that method for invocation. Otherwise proceed to the next step. They are used only to determine which overloadings are applicable

The second phase: It selects the most specific of the methods or constructors selected in the first phase,  it selects the most specific overloading, using only the formal parameters: the parameters appearing in the declaration  . If there exists either an 
1) exact match
 2) widening type conversion
 from each of the parameters of a method in the set to the corresponding parameters of another method, eliminate the latter method from the set. 
If you are left with only one method after pruning the set in this manner, select that method for invocation. Otherwise proceed to the next step.

The third phase: Declare the source code invalid because there does not exist a single maximally specific method that can be invoked for the function call.

Consider the following example:


//Overload.Java

class Employee {String name;}

class Manager extends Employee {int level;}

class Test {
    static void foo(Employee e1, Employee e2) {    //first foo   //(A)
        System.out.println( "first foo");
    }
    static void foo(Employee e, Manager m) {       //second foo  //(B)
        System.out.println( "second foo");
    }
    static void foo(Manager m, Employee e) {       //third foo   //(C)
        System.out.println( "third foo");
    }
    public static void main(String[] args)
    {
        Employee emp = new Employee ();
        Manager man = new Manager();

        foo(emp, man);        // will invoke the second foo      //(D)
        //foo(man, man);      // Error because it produces an    //(E)
                              // ambiguity in overload resolution
  }
}


When we call ---à foo(emp,man)
Phase 1

Find set of applicable methods, i.e exact match and widened type conversion, also here actual parameters  are considered, i.e parameters called during invocation :
A)     foo(Employee e1, Employee e2)-à foo(emp,man)
emp is exact match, man is an employee object( widened type ,comparing with actual parameters)à so pass
B)     foo(Employee e, Manager m) à foo(emp, man)
emp is exact match, man is an exact match with man-à so pass
C)     foo(Manager m, Employee e)à foo(emp,man)
emp object is not always a manager object—not pass (taking formal parameters into consideration)
every manager object is an employee object..
So end of Phase 1: {A, B}

Phase 2: {A, B}
A--> has one exact match and other widened match
B--> have both exact match

So, eliminate the one who has widened match, in our case A
Hence, B--> foo (Employee e, Manager m) would be called

Now consider that happens if we uncomment the call to foo in line (E). Its argument types match the parameter types for all three definitions of foo. So at the end of the first step of overload resolution, we have three candidates in the set.
 By the same reasoning as before, we now discover that the first definition of foo is less specific than the other two. So we delete it from the set. However, we also discover that it is not possible to delete either of the remaining two entries from the set, for the simple reason that an Employee type does not possess a widening type conversion to a Manager type. So we declare ambiguity and, therefore, compile time error results.


If you have many types and this is unmanageable, then method overloading is probably not the right approach, rather the public method should just take Object and implement some kind of strategy pattern to delegate the appropriate handling per object type.

Ability to dispatch a call to a method based on types of arguments is called multiple dispatch. In Java this is done with Visitor pattern..



References: