Static and Dynamic Polymorphism in Java

What is Polymorphism?

Polymorphism is composed of two words, poly ( meaning many) and morphs (meaning forms). It means having many forms in different situations.  Let us take a real-life example. We all are aware of the word orange. It is the name of a fruit and color. The meaning of a single word differs depending on the context of the discussion.

Polymorphism is one of the features of an object-oriented paradigm. It allows us the flexibility to do a single process in different ways.

Types of Polymorphism

The polymorphism is divided into two different types depending on the resolution of form to execute.

  • Static Polymorphism
  • Dynamic Polymorphism

Static Polymorphism

The polymorphism where the form to execute gets identified/resolved at the compile time is known as static polymorphism. Method Overloading and Operator overloading are a few of the examples of static polymorphism.

1. Method Overloading

When a class has more than one method with the same name but a different signature, it is known as method overloading. The signature can be altered by changing the number, order, and/or data type of parameters.

Let us look at one example. We have class MyCalculator that has 4 versions of add method. Each has a different signature. As a result, at the time of compiling, it is known which version of add is to be used. It is also known as early binding

class MyCalculator{
    //Version 1
    int add(int a, int b){
        System.out.println("I am add method that adds two integers");
        return(a+b);
    }
    //Version 2
    int add(int a, int b, int c){
        System.out.println("I am add method that adds three integers");
        return(a+b+c);
    }
    //Version 3
    float add(float a, float b){
        System.out.println("I am add method that adds two floats");
        return(a+b);
    }
    //Version 4
    float add(float a, float b, float c){
        System.out.println("I am add method that adds three floats");
        return(a+b+c);
    }
}

public class ClassMain{
    public static void main(String args[]){
        MyCalculator obj = new MyCalculator();
        System.out.println("2 + 3 = "+obj.add(2,3));
        System.out.println("2 + 3 + 4 = "+obj.add(2,3,4));
        System.out.println("2.2 + 3.3 = "+obj.add(2.2f,3.3f));
        System.out.println("2.2 + 3.3 + 4.4 = "+obj.add(2.2f,3.3f,4.4f));
    }
}

Output:

I am add method that adds two integers
2 + 3 = 5
I am add method that adds three integers
2 + 3 + 4 = 9
I am add method that adds two floats
2.2 + 3.3 = 5.5
I am add method that adds three floats
2.2 + 3.3 + 4.4 = 9.9

2. Operator Overloading

 In Java, user-defined operator overloading is not supported. The one operator which already comes overloaded is + operator. When used with numbers, it acts as an addition operator, whereas when used with string, it concatenates. Let us look at one example:

class MyOperatorOverloaded{
    int plus(int a, int b){
        System.out.println("I am plus method that adds two integers");
        return(a+b); //adds 2 integers
    }

    float plus(float a, float b){
        System.out.println("I am plus method that adds two floats");
        return(a+b); //adds 2 floats
    }
    
    String plus(String a, String b){
        System.out.println("I am plus method that concatenates two strings");
        return(a+b); //concatenates two strings
    }
}


public class ClassMain{
    public static void main(String args[]){
        MyOperatorOverloaded obj = new MyOperatorOverloaded();
        System.out.println("2 + 3 = "+obj.plus(2,3));
        System.out.println("2.2 + 3.3 = "+obj.plus(2.2f,3.3f));
        System.out.println("Madhu + rav = "+obj.plus("Madhu","rav"));
    }
}

Output:

I am plus method that adds two integers
2 + 3 = 5
I am plus method that adds two floats
2.2 + 3.3 = 5.5
I am plus method that concatenates two strings
Madhu + rav = Madhurav

Dynamic Polymorphism

The polymorphism where the form to execute gets identified/resolved at the run time is known as dynamic polymorphism. Method Overriding is a way to perform dynamic polymorphism. Overriding is not applicable to data members.

Method Overriding

When two classes share IS-A relationship such that, the child class overrides the inherited method from the parent class, it is called method overriding.

Let us see an example for clarity. There are two classes, Parent and Child. The Child inherits class Parent and overrides write(int a, String b) method. parObj is a Parent class variable and as stated in our previous lecture, the parent class variable can hold a reference to it's immediate and successors child class(in case of multilevel inheritance). The version of write method is resolved on the basis of the reference that the variable holds at the instant of the method invocation. Note the difference in line number 16 and 18. At line number 16, parObj holds the reference of the parent object. As a result, the parent's write method is invoked. Similarly,  parObj holds the reference of the child object at line number 18. As a result, the child's write method is invoked

class Parent{
    void write(int a, String b){
        System.out.println("I am Parent version. Data: (a,b) = ("+a+","+b+")");
    }
}

class Child extends Parent{
    void write(int a, String b){
        System.out.println("I am Child version.  Data: [int a = "+a+", String b= "+b+"]");
    }
}

public class ClassMain{
    public static void main(String args[]){
        Parent parObj = new Parent();
        parObj.write(25,"Gouri");  //parObj holds reference of class Parent
        parObj = new Child();
        parObj.write(25,"Gouri");  //parObj holds reference of class Child
    }
}

Output:

I am Parent version. Data: (a,b) = (25,Gouri)
I am Child version.  Data: [int a = 25, String b= Gouri]

This was an overview of Java Polymorphism. We will discuss the final keyword in the next lecture.