What is dynamic method dispatch in Java?

Dynamic method dispatch is the mechanism in which a call to an overridden method is resolved at run time instead of compile time. This is an important concept because of how Java implements run-time polymorphism.

Java uses the principle of ‘a superclass reference variable can refer to a subclass object’ to resolve calls to overridden methods at run time. When a superclass reference is used to call an overridden method, Java determines which version of the method to execute based on the type of the object being referred to at the time call.

In other words, it is the type of object being referred to that determines which version of an overridden method will be executed.

Advantages of dynamic method dispatch

  1. It allows Java to support overriding of methods, which are important for run-time polymorphism.
  2. It allows a class to define methods that will be shared by all its derived classes, while also allowing these sub-classes to define their specific implementation of a few or all of those methods.
  3. It allows subclasses to incorporate their own methods and define their implementation.

Dynamic method: single levels of inheritance.

Here is an example illustrating dynamic method dispatch:

// Implementing Dynamic Method Dispatch
class Apple
{
void display()
{
System.out.println("Inside Apple's display method");
}
}
class Banana extends Apple
{
void display() // overriding display()
{
System.out.println("Inside Banana's display method");
}
}
class Cherry extends Apple
{
void display() // overriding display()
{
System.out.println("Inside Cherry's display method");
}
}
class Fruits_Dispatch
{
public static void main(String args[])
{
Apple a = new Apple(); // object of Apple
Banana b = new Banana(); // object of Banana
Cherry c = new Cherry(); // object of Cherry
Apple ref; // taking a reference of Apple
ref = a; // r refers to a object in Apple
ref.display(); // calling Apple's version of display()
ref = b; // r refers to a object in Banana
ref.display(); // calling Banana's version of display()
ref = c; // r refers to a object in Cherry
ref.display(); // calling Cherry's version of display()
}
}

This program creates one superclass (i.e., class Apple) and two subclasses of it (i.e., Banana class and Cherry class). Subclasses Banana and Cherry override the display() method declared in Apple. Inside the main() method in class Fruits_Dispatch, objects of type Apple, Banana, and Cherry are declared. A reference of type Apple, called ref, is declared.

The program then assigns a reference to each type of object to ref and uses the reference to invoke display().

The version of display() executed is determined by the type of the object being referred to at the time of the call.

Dynamic method: multiple levels of inheritance.

Now let's enhance our understanding further by reviewing another coding example where we will see how dynamic method dispatch works with multiple levels of inheritance.

// Implementing Dynamic Method Dispatch with Multiple Inheritance Levels
// Superclass
class Fruit {
void display() {
System.out.println("Inside Fruit's display method");
}
}
// Subclass 1
class Apple extends Fruit {
void display() {
System.out.println("Inside Apple's display method");
}
}
// Subclass 2
class Banana extends Fruit {
void display() {
System.out.println("Inside Banana's display method");
}
}
// Subclass 3
class Cherry extends Fruit {
void display() {
System.out.println("Inside Cherry's display method");
}
}
// Subclass 4
class Orange extends Fruit {
void display() {
System.out.println("Inside Orange's display method");
}
}
// Driver class
class Main {
public static void main(String[] args) {
Fruit ref; // Reference variable of type Fruit
// Object of type Apple
ref = new Apple();
ref.display(); // Calls Apple's display() method
// Object of type Banana
ref = new Banana();
ref.display(); // Calls Banana's display() method
// Object of type Cherry
ref = new Cherry();
ref.display(); // Calls Cherry's display() method
// Object of type Orange
ref = new Orange();
ref.display(); // Calls Orange's display() method
}
}

In this example, we have added another subclass Orange inheriting from Fruit. The display() method is overridden in each subclass. When different objects are created, their display() method is called using the reference of type Fruit, Java determines at runtime which version of display() to execute based on the actual type of the object being referred to.

Thanks for reading :)