Way2Java

Java Dynamic Binding Dynamic Polymorphism

Static binding and static polymorphism is achieved through method overloading. Now let us go for dynamic polymorphism. Observe the following code.

Program of Java Dynamic Binding Dynamic Polymorphism
class Bird
{
  public void eat()			// I
  {
    System.out.println("All birds eat");
  }
}
class Peacock extends Bird
{
  public void eat()			// II
  {
    System.out.println("Peacock eats grains");
  }
}
class Vulture extends Bird
{
  public void eat()			// III
  {
    System.out.println("Vulture eats flesh");
  }
}
class Crane extends Bird
{
  public void eat()			// IV
  {
    System.out.println("Crane eats fish");
  }
}
public class DynamicPolyDemo
{
  public static void main(String args[])
  {
    Bird b1 = new Bird();                       b1.eat();     // calls I
    Peacock p1 = new Peacock();   b1 = p1;	b1.eat();     // calls II
    Vulture v1 = new Vulture();   b1 = v1;	b1.eat();     // calls III
    Crane c1 = new Crane();       b1 = c1;	b1.eat();     // calls IV
 }
}



Output screen of Java Dynamic Binding Dynamic Polymorphism

In the above code, Bird is inherited by three classes – Peacock, Vulture and Crane. It is an example of hierarchical inheritance.

Subclasses Peacock, Vulture and Crane overrides the eat() method of Bird.

	
       b1 = p1;	
       b1.eat();     

In the above statement, subclass Peacock object p1 is assigned to super class Bird object b1. Earlier, in Object Casting, we know if a subclass object is assigned to a super class object, the super class object will call subclass overridden method. As per this rule, b1 will call p1 eat() method. Infact, the b1 contains the reference of p1.

       b1 = v1;	
       b1.eat();     

Now, the Bird object b1 is assigned with the subclass Vulture object v1. Now the earlier p1 reference is replaced by v1. Now b1 points to v1 location. Now b1 calls v1 eat method.

                         
       b1 = c1;	
       b1.eat();   

Again, the v1 reference in the super class object b1 is replaced by Crane object c1. Now, b1 calls Crane's eat() method.

Observe the code, the statement b1.eat() prints 4 different outputs by calling 4 different eat() methods. The same method when called different times giving different values is known a polymorphism ("poly" means many and "morphism" means forms).

Java Dynamic Binding

Which eat() method is to be called is decided at runtime because in every statement the address of the earlier subclass object is replaced. This address replacement happens at runtime (and not at compile time). Which overridden method is to be called is decided (or binded) dynamically at runtime. This feature is known as dynamic binding. Because polymorphism is achieved dynamically at runtime, this is known as dynamic polymorphism.

Dynamic binding is also called as dynamic method dispatch as which overridden method is to be dispatched for execution is known at runtime.

Rules followed to achieve dynamic polymorphism

1. There must be method overriding.
2. Subclass object must be assigned to a super class object.

The rule followed is "when a subclass object is assigned to a super class object, the super object will call subclass overridden method".

We know earlier, static polymorphism which is achieved through method overloading.

Dynamic polymorphism through Interfaces

The same Bird program, in the earlier example, can be modified to suit with interfaces. Now declare Bird as an interface. We know that reference variables can be created with abstract classes and interfaces (but not objects). Read the following program.

interface Bird
{
  public abstract void eat();		// I
}
class Peacock implements Bird
{
  public void eat()			// II
  {
    System.out.println("Peacock eats grains");
  }
}
class Vulture implements Bird
{
  public void eat()			// III
  {
    System.out.println("Vulture eats flesh");
  }
}
class Crane implements Bird
{
  public void eat()			// IV
  {
    System.out.println("Crane eats fish");
  }
}
public class DynamicPolyDemo
{
  public static void main(String args[])
  {
    Bird b1;		// reference variable of interface
    Peacock p1 = new Peacock();	b1 = p1;	b1.eat();     // calls II
    Vulture v1 = new Vulture();	b1 = v1;	b1.eat();     // calls III
    Crane c1 = new Crane();	b1 = c1; 	b1.eat();     // calls IV
  }
}

Here Bird is interface and not a concrete class (in the earlier program it is concrete class).

  
       Bird b1;

b1 is reference variable and not object.

       b1 = p1;		
       b1.eat();

Subclass Peacock object is assigned to the reference variable b1 of interface Bird. Here, super class is an interface and eat() is an abstract method. When a subclass object is assigned to a super class reference variable, the reference variable calls subclass overridden method. Now, b1 calls subclass Peacock's eat() method.

The addresses of subclass objects, p1, v1 and c1, in the super class reference variable b1 are replaced in every statement dynamically at runtime. Every time when b1.eat() method is called, it prints different outputs. This is known as polymorphism. Because polymorphism is achieved at runtime dynamically, this is known as dynamic polymorphism. Here, dynamic polymorphism is achieved through interfaces.