Polymorphism in Java

Rumman Ansari   Software Engineer   2021-01-05   8555 Share
☰ Table of Contents

Table of Content:


Polymorphism is derived from 2 greek words: poly and morphs. The word "poly" means many and "morphs" means forms. So polymorphism means many forms. Polymorphism means that a variable of a supertype can refer to a subtype object. There are two types of polymorphism in java:
1. Compile time polymorphism
2. Runtime polymorphism.
We can perform polymorphism in java by method overloading and method overriding.

If you overload static method in java, it is the example of compile time polymorphism.

Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.

Runtime Polymorhism( or Dynamic polymorphism)

Runtime polymorphism or Dynamic Method Dispatch is a process in which a call to an overridden method is resolved at runtime rather than compile-time.


Method overriding is a perfect example of runtime polymorphism. In this kind of polymorphism, reference of class X can hold object of class X or an object of any sub classes of class X. For e.g. if class Y extends class X then both of the following statements are valid:

 
 Y obj = new Y();
//Parent class reference can be assigned to child object
X obj = new Y();
 

Since in method overriding both the classes(base class and child class) have same method, compile doesn’t figure out which method to call at compile-time. In this case JVM(java virtual machine) decides which method to call at runtime that’s why it is known as runtime or dynamic polymorphism.


Lets see an example to understand it better.

Program:

 public class X
{
    public void methodA() //Base class method
    {
        System.out.println ("hello, I'm methodA of class X");
    }
}

public class Y extends X
{
    public void methodA() //Derived Class method
    {
        System.out.println ("hello, I'm methodA of class Y");
    }
}
public class Z
{
   public static void main (String args []) {
       X obj1 = new X(); // Reference and object X
       X obj2 = new Y(); // X reference but Y object
       obj1.methodA();
       obj2.methodA();
   }
}
 

Output:

 hello, I'm methodA of class X
hello, I'm methodA of class Y
 

As you can see the methodA has different-2 forms in child and parent class thus we can say methodA here is polymorphic.

Dynamic binding

When type of the object is determined at run-time, it is known as dynamic binding. Example of dynamic binding

Program:

class Animal{
 void eat(){
	 System.out.println("animal eat method...");
	 }
}

class Cow extends Animal{
 void eat(){
	 System.out.println("Cow eat method...");
	 }

 public static void main(String args[]){
  Animal a=new Cow();
  a.eat();
 }
}
 
Output:
Cow eat method...
Press any key to continue . . .
 

In the above example object type cannot be determined by the compiler, because the instance of Cow is also an instance of Animal. So compiler doesn't know its type, only its base type.

Compile time Polymorhism( or Static polymorphism)

Compile time polymorphism is nothing but the method overloading in java. In simple terms we can say that a class can have more than one methods with same name but with different number of arguments or different types of arguments or both. To know more about it refer method overloading in java.

Program:

class ClassX
{
   void methodA(int num)
   {
       System.out.println ("methodA:" + num);
   }
   void methodA(int num1, int num2)
   {
       System.out.println ("methodA:" + num1 + "," + num2);
   }
   double methodA(double num) {
       System.out.println("methodA:" + num);
       return num;
   }
}

class ClassY
{
   public static void main (String args [])
   {
       ClassX Obj = new ClassX();
       double result;
       Obj.methodA(22);
       Obj.methodA(21, 10);
       result = Obj.methodA(2.5);
       System.out.println("Answer is:" + result);
   }
}
 
Output:
methodA:22
methodA:21,10
methodA:2.5
Answer is:2.5
Press any key to continue . . .
 

As you can see in the above example that the class has three variance of methodA or we can say methodA is polymorphic in nature since it is having three different forms. In such scenario, compiler is able to figure out the method call at compile-time that's the reason it is known as compile time polymorphism.

Difference between Runtime Polymorphism and Compile time Polymorphism

Compile time Polymorphism

Runtime Polymorphism

In Compile time Polymorphism, the call is resolved by the compiler. In Run time Polymorphism, the call is not resolved by the compiler.
It is also known as Static binding, Early binding and overloading as well. It is also known as Dynamic binding, Late binding and overriding as well.
Overloading is compile time polymorphism where more than one methods share the same name with different parameters or signature and different return type. Overriding is run time polymorphism having the same method with same parameters or signature, but associated with a class & its subclass.
It is achieved by method overloading. It is achieved by method overriding
It provides fast execution because known early at compile time. It provides slow execution as compared to early binding because it is known at runtime.
Compile time polymorphism is less flexible as all things execute at compile time. Run time polymorphism is more flexible as all things execute at run time.

Upcasting

When reference variable of Parent class refers to the object of Child class, it is known as upcasting. For example:

class Parent{
..............
..............
..............
}  

class Child extends Parent{
..............
..............
..............
}  
 
Parent a=new Child();//upcasting   
 

Is it possible Java Runtime Polymorphism with Data Member ?

Method is overridden not the datamembers, so runtime polymorphism can't be achieved by data members.

Note: Runtime polymorphism can't be achieved by data members.

Program:

class Car{
 int speedlimit=96;
}
class Bike extends Car{
 int speedlimit=150;

 public static void main(String args[]){
  Car obj=new Bike();
  System.out.println(obj.speedlimit);//90
 }
}
 
Output:
96
Press any key to continue . . .
 

In the above example, both the classes have a datamember speedlimit, we are accessing the datamember by the reference variable of Parent class which refers to the subclass object. Since we are accessing the datamember which is not overridden, hence it will access the datamember of Parent class always.

Java Runtime Polymorphism with Multilevel Inheritance

Program:

class Animal{
	void eat(){
		System.out.println("eating Animal");
		}
}

class Cow extends Animal{
	void eat(){
		System.out.println("eating Grass");
		}
}

class Calf extends Cow{
	void eat(){
		System.out.println("drinking milk");
		}

	public static void main(String args[]){
	Animal a1,a2,a3;
	a1=new Animal();
	a2=new Cow();
	a3=new Calf();
	a1.eat();
	a2.eat();
	a3.eat();
	}
}
 
Output:
eating Animal
eating Grass
drinking milk
Press any key to continue . . .
 

In the above example, both the classes have a datamember speedlimit, we are accessing the datamember by the reference variable of Parent class which refers to the subclass object. Since we are accessing the datamember which is not overridden, hence it will access the datamember of Parent class always.

static binding

When type of the object is determined at compiled time(by the compiler), it is known as static binding. If there is any private, final or static method in a class, there is static binding.

Example of static binding

Program:

class Cow{
 private void eat(){
	 System.out.println("Cow is eating...");
	 }

 public static void main(String args[]){
  Cow d1=new Cow();
  d1.eat();
 }
}
 
Output:
Cow is eating...
Press any key to continue . . .