Let us begin with understanding of the word polymorphism. The word has a greek origin from words polus/polloi and morphe. ‘Poly’ means ‘many’ and ‘Morph’ means forms. So when any entity has many forms according to its context of use, we may call it polymorphism. This nomenclature is frequently used in biological studies. For e.g. Hepatitis virus is said to be polymorphic as it has many strains.
In english language the homonyms words are also a form of polymorphism only. For e.g. the word “date” can have different meaning in different contexts. This is clear from the following diagram.
Fig 1: English homonyms depicting polymorphism
Let us take an example of computer science. Suppose we write
a=5; b=7; int c=a+b; //result in c would be integer addition of a and b which would be 12
// in case of
string x="poly"; string y="morphism";
string z=a+b; //result in z would be string concatenation as polymorphism
Here the + (addition) operator takes two different forms. First one to add numbers and second one to concatenate strings.
The same example can be diagramatically understood as follows.
Fig. 2: Operator + being used in two different forms
Let us understand it a bit further. Suppose we write two functions as follows.
float add(float x, float y); //Definition 1
int add(int a, int b); //Definition 2
Here the internal implementation code of these functions will definitely be different as the way to add integer numbers and fractional numbers are different. This is typically known as function overloading. In a way it is also polymorphism.
When we explore further we will come across more dimensions of this term polymorphism in context of computer science. Some times experts differ on exact definition of polymorphism. For instance in the above example of function overloading compiler is able to create two separate code bodies for each of the parameter types and in real calls to the code, references are not really dynamic in nature. If call is with float parameters the code portion referenced by definition 1 is reached and if the call is with integer parameters code portion referenced by definition 2 is reached.
So let us classify polymorphism on the basis of its dynamism.
- Compile time polymorphism (Static Polymorphism)
- Run time polymorphism (Dynamic Polymorphism)
Compile Time Polymorphism (Static)
In this type of polymorphism the names of called entities (functions, operators or variables) are same but compiler is able to identify the differences and use it as per the input parameters or other input conditions. In this type the entities may appear to be polymorphic but in real sense at run time they have clearly defined separate references. For this reason experts call it as adhoc polymorphism or sometimes they do not consider at polymorphism.
The example of operator with overloaded use and function as overloaded functions given above come under this category.
Run Time Polymorphism (Dynamic)
In this type of polymorphism the reference code at the run time is also same and variation in execution is dependent on how it has been called. This is often the case when polymorphism is implemented in inherited classes.
Consider the following example.
#include <iostream>
using namespace std;
class Mammal
{
public:
virtual void fly(){cout<<"Mammals don't fly"<<endl;}
};
class Bat:public Mammal
{
public:
void fly(){cout<<"Bats are exceptions they fly"<<endl;}
};
void Doesfly(Mammal *m) { m->fly();}
int main()
{
Bat b; Mammal m;
Doesfly(&m);
Doesfly(&b);
return 0;
}
The output of above code when run us is as follows.
Mammals don't fly
Bats are exceptions they fly
In the above code the function doesfly() parameters are of same type when they are called but each time they will call a different function based on which object has been passed to it. You can see that this different from function overloading. Only one function Doesfly() has been called but its impact is different.
This is because parent Mammal has a virtual function fly() and child class Bat has a overrided function fly. Since both superclass and subclass reference is type compatible so we can always write some function (Which is doesfly() in this case) with a parameter of type Superclass and still pass the subclass to it.
Since this selection of function call based on which reference has been passed happens at the run time, we call it runtime polymorphism or dynamic polymorphism. Some times people also call it subtype polymorphism.
Other Types of Polymorphism
Coercion Polymorphism
Sometimes people call typecasting also as a type of polymorphism only. For e.g. if I say
double a=12.5;
int b=(int) a;
In the above case we can clearly see that variable a will exist in two forms. One in the double form and another in the integer form due to the casting operator (int) applied to it. So this in a way is also aform of polymorphism only.
Parametric Polymorphism
In C++ this type of polymorphism although not implemented in its Ideal form can still be indirectly achieved. Description is currently out of scope of this article, but interested learners can still try to follow the links given here.
http://www.catonmat.net/blog/cpp-polymorphism/
http://www.cplusplus.com/doc/tutorial/polymorphism/
https://en.wikipedia.org/wiki/Parametric_polymorphism