Dear Folks !
Polymorphism is an important feature of object oriented programming paradigm. This makes the language dynamic.(due to this, easy up-gradation/extensibility of software is possible).
The literal meaning is many forms, i.e one name - many forms. In programming context, it is one method/object with different behaviors under different contexts. In our day-to-day activities we often demonstrate this feature. This image would make us realize it.
Polymorphism can be implemented at compile-time and run-time of the program. It basically depends on binding(or linking) time of a method call to method definition.
If the information, to bind a call to it's definition is available at compile-time of the program,then we can implement compile-time polymorphism.(static polymorphism).
In C++/Java we implement it, by function/method overloading. For overloading, the condition is that, the methods must have same method name, but vary at least with regard to any one criterion listed below...
(i) Number of arguments
(ii) Type of arguments
If we can create a mismatch among the methods being overloaded, using these two parameters, then, the compiler can uses this, to discriminate the calls and accordingly bind the call to definitions at compile-time.
Note: The return-type information is useless in overloading, hence bears no significance w.r.t compile-time polymorphism.
/* Let's demonstrate it in C++ */
float compuTax(float gross_sal)
{
return 20*gross_sal/100;
}
float compuTax(float gross_sal, float bonus)
{
return (20*gross_sal/100) + (30*bonus/100) ;
}
void main()
{
-----
-----
tax2=compuTax(700000,299999);
-----
}
Notice here, the return type for both methods is same, still overloading is possible. The mismatch is been created using argument numbers.
Let's check , how it works...
In C++, operator overloading uses compile-time polymorphism.
Now, Let's explore run-time polymorphism...
We know, if the mismatch is not created either in terms of number of arguments or type of arguments, then method overloading is not possible, as the compiler fall short of information to link the calls, to their respective definitions.In such scenarios since the compiler has no information, it postpones the job of binding till run-time of the program. At run-time, the system will link the method calls to the respective definitions, based on the information made available to it during run-time.Hence it is called dynamic ploymorphism.
In C++ it is implemented using virtual functions, and in Java, it is implemented using dynamic dispatch of methods.
Let's see how it's implemeted in Java...
class Employee // super class
{
protected double sal;
void init(double x) { sal=x;}
double compuTax(){ return 0.2*sal; }
}
class Manager extends Employee
{
protected double bonus;
void setBonus(double x){ bonus=x;}
double compuTax(){return 0.2*sal + 0.3* bonus ;}
}
class DemoPoly
{
public static void main(String args[])
{
Employee empref;
Employee tom = new Employee();
tom.init(50000);
Manager jerry=new Manager();
jerry.init(70000);
jerry.setBonus(10000);
double tom_tax, jerry_tax;
empref=tom;
tom_tax= empref.compuTax();
empref=jerry;
jerry_tax=empref.compuTax();
System.out.println("Tom has to pay a tax of "+tom_tax);
System.out.println("Jerry has to pay a tax of "+jerry_tax);
} // end of main method
}
Output
Tom has to pay a tax of 10000
Jerry has to pay a tax of 17000
You can notice here that the calls(in red) have same signature, i.e same argument type and number, as compiler is not able to bind, it postpones till run-time. The run-time system, checks what is being represented at this instant,by superclass (empref) reference, and then accordingly links and calls the method of that class/object.
If the superclass reference is representing employee, compuTax() of Employee is called, if it is representing manager, compuTax() of manager is called and so on...
You would appreciate this feature, after going through the following scenario.
Say, you want to add one more new class to your existing system, let's say class Supervisor, you will do it like this...
class Supervisor extends Employee
{
protected double overtime_package;
void setpackage(double x){ overtime_package=x;}
double compuTax(){ return 0.2*sal + 0.15* overtime_package ;}
}
class DemoPoly
{
public static void main(String args[])
{
Employee empref;
Employee tom = new Employee();
tom.init(50000);
Manager jerry=new Manager();
jerry.init(70000);
jerry.setBonus(10000);
double tom_tax, jerry_tax,peter_tax;
empref=tom;
tom_tax= empref.compuTax();
empref=jerry;
jerry_tax=empref.compuTax();
Supervisor peter=new Supervisor()
empref=peter;
peter_tax= empref.compuTax();
System.out.println("Tom has to pay a tax of "+tom_tax);
System.out.println("Jerry has to pay a tax of "+jerry_tax);
System.out.println("Peter has to pay a tax of "+peter_tax);
} // end of main method
}
This is how due to dynamic polymorphism, easy up-gradation or extensibility of software is possible. This is how we make the old code use new code, with little changes or no changes in existing code ...
How do you justify that, birds in this image are demonstrating polymorphic behavior !!!
Did you find this article worth reading ? please comment...
Let's share to grow and grow to share...
Let's check , how it works...
In C++, operator overloading uses compile-time polymorphism.
Now, Let's explore run-time polymorphism...
We know, if the mismatch is not created either in terms of number of arguments or type of arguments, then method overloading is not possible, as the compiler fall short of information to link the calls, to their respective definitions.In such scenarios since the compiler has no information, it postpones the job of binding till run-time of the program. At run-time, the system will link the method calls to the respective definitions, based on the information made available to it during run-time.Hence it is called dynamic ploymorphism.
In C++ it is implemented using virtual functions, and in Java, it is implemented using dynamic dispatch of methods.
Let's see how it's implemeted in Java...
class Employee // super class
{
protected double sal;
void init(double x) { sal=x;}
double compuTax(){ return 0.2*sal; }
}
class Manager extends Employee
{
protected double bonus;
void setBonus(double x){ bonus=x;}
double compuTax(){return 0.2*sal + 0.3* bonus ;}
}
class DemoPoly
{
public static void main(String args[])
{
Employee empref;
Employee tom = new Employee();
tom.init(50000);
Manager jerry=new Manager();
jerry.init(70000);
jerry.setBonus(10000);
double tom_tax, jerry_tax;
empref=tom;
tom_tax= empref.compuTax();
empref=jerry;
jerry_tax=empref.compuTax();
System.out.println("Tom has to pay a tax of "+tom_tax);
System.out.println("Jerry has to pay a tax of "+jerry_tax);
} // end of main method
}
Output
Tom has to pay a tax of 10000
Jerry has to pay a tax of 17000
You can notice here that the calls(in red) have same signature, i.e same argument type and number, as compiler is not able to bind, it postpones till run-time. The run-time system, checks what is being represented at this instant,by superclass (empref) reference, and then accordingly links and calls the method of that class/object.
If the superclass reference is representing employee, compuTax() of Employee is called, if it is representing manager, compuTax() of manager is called and so on...
You would appreciate this feature, after going through the following scenario.
Say, you want to add one more new class to your existing system, let's say class Supervisor, you will do it like this...
class Supervisor extends Employee
{
protected double overtime_package;
void setpackage(double x){ overtime_package=x;}
double compuTax(){ return 0.2*sal + 0.15* overtime_package ;}
}
class DemoPoly
{
public static void main(String args[])
{
Employee empref;
Employee tom = new Employee();
tom.init(50000);
Manager jerry=new Manager();
jerry.init(70000);
jerry.setBonus(10000);
double tom_tax, jerry_tax,peter_tax;
empref=tom;
tom_tax= empref.compuTax();
empref=jerry;
jerry_tax=empref.compuTax();
Supervisor peter=new Supervisor()
empref=peter;
peter_tax= empref.compuTax();
System.out.println("Tom has to pay a tax of "+tom_tax);
System.out.println("Jerry has to pay a tax of "+jerry_tax);
System.out.println("Peter has to pay a tax of "+peter_tax);
} // end of main method
}
This is how due to dynamic polymorphism, easy up-gradation or extensibility of software is possible. This is how we make the old code use new code, with little changes or no changes in existing code ...
How do you justify that, birds in this image are demonstrating polymorphic behavior !!!
Did you find this article worth reading ? please comment...
Let's share to grow and grow to share...
No comments:
Post a Comment