What is polymorphism? Explain with real life examples? Types of polymorphism in details

In interviews, typically  question is asked: "What is polymorphism?"

And surprisingly, in most cases, the answer is: "polymorphism means many forms."

In response, the next question is typically: "What do you mean by many forms?"
The most common answer is: "There are two types of polymorphism — runtime polymorphism and static polymorphism. Method overriding is an example of runtime polymorphism, and method overloading is an example of static polymorphism."
Obviously, we know why method overriding is called "runtime polymorphism" and why "method overloading" is called "static polymorphism." But it is difficult from these answers to come to a conclusion as to what they meant by 'many forms.' And although method overloading and method overriding are polymorphism, why are they polymorphism?

Basically, the best uses of polymorphism in Java is the ability to refer to a child class by using the parent class reference. In polymorphism, 'many forms' means the ability of an object or method to take many forms. Method overriding and method overloading basically mean a behavior in Java that allows the developer to take advantage of that principle.

Real Life Example 1: In the real world, you might have seen a chameleon changing its color as per its requirement. If someone asks, “How it does that?”, you can simply say, “Because, it is polymorphic”. 

Real Life Example 2: A security guard outside an organization behaves differently with different people entering the organization. He acts in a different way when the Boss comes and, in another way when the employees come. When the customers enter, the guard will respond differently. So here, the behavior of the guard is in various forms, which depends on the member who is coming.
Real Life Example 3:
Currency is one which is used to buy or sell anything all over world.
but representation or format of currency in each country is different. like India has RS as currency, US has dollar as currency etc.

Type of Polymorphism:

  Java supports two types of polymorphism and they are as follows:
  1. Static Polymorphism
  2. Dynamic Polymorphism
Static Polymorphism:
A polymorphism that is resolved during compile time is known as static polymorphism. Method overloading is an example of compile time polymorphism. Therefore, this type of polymorphism is also called compile-time polymorphism. Since binding is performed at compile-time, it is also known as early binding. Compile-time polymorphism can be achieved/implemented by method overloading in java.
Method overloading is a mechanism in which a class has multiple methods having the same name but different signatures. It is one of the ways that Java implements polymorphism.
Constructor overloading and method hiding is another examples of static polymorphism.

Method Overloading example:
Method Overloading is a feature that allows a class to have two or more method to have the same name, but with different parameter lists. In the below example, you have two definitions of the same method add(). So, which add() method would be called is determined by the parameter list at the compile time. That is the reason this is also known as compile time polymorphism.
class Calculator
{
    int add(int x, int y)
    {
        return x+y;
    }
    int add(int x, int y, int z) 
    {
        return x+y+z;
    }
}
public class Test
{
    public static void main(String args[])
    {
        Calculator obj = new Calculator();
        System.out.println(obj.add(100, 200));
        System.out.println(obj.add(100, 200, 300));
    }
}
This is how Static Polymorphism works.If you are looking for method overloading in JDK classes, you will find a lot of them in the String and primitive wrapper classes. For example, String valueOf() methods, Integer parseInt() methods, etc.

Constructor Overloading Example:
Suppose we have a 'Student' class and while making its object, we want to pass a name of it and if nothing is passed, then name should be "unknown". And yes! we can do this by having two constructors.
class Student{
  private String name;
  public Student(String n){
    name = n;
  }
  public Student(){
    name = "unknown";
  }
  public void printName(){
    System.out.println(name);
  }
}
class Cu1{
  public static void main(String[] args){
    Student a = new Student("Aashish");
    Student b = new Student();
    a.printName();
    b.printName();
  }
}
Output: Aashish
        unknown
Dynamic Polymorphism:
Dynamic polymorphism is a process in which a call to an overridden method is resolved at runtime, that’s why it is called runtime polymorphism. Method Overriding is one of the ways to achieve Dynamic Polymorphism. In any object-oriented programming language, Overriding is a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes.

Example:
In the below example, you have two classes MacBook and iPad. MacBook is a parent class and iPad is a child class. The child class is overriding the method myMethod() of the parent class. Here, I have assigned child class object to the parent class reference to determine which method would be called at run-time. It is the type of object that determines which version of the method would be called (not the type of reference).

class MacBook{
    public void myMethod(){
        System.out.println("In MacBook myMethod
()");
    }
}
public class iPad extends MacBook{
    public void myMethod(){
        System.out.println("In iPad myMethod
()");
    }
    public static void main(String args[]){
        MacBook obj = new iPad();
        obj.myMethod();
    }
}
Output: In iPad myMethod()
Advantages of Dynamic Polymorphism:
  1. Dynamic Polymorphism allows Java to support overriding of methods which is central for run-time polymorphism. 
  2. It allows a class to specify methods that will be common to all of its derivatives while allowing subclasses to define the specific implementation of some or all of those methods.
  3. It also allows subclasses to add its specific methods subclasses to define the specific implementation of same. 
Other Characteristics of Polymorphism in Java:
In addition to these two main types of polymorphism in Java, there are other characteristics in the Java programming language that exhibits polymorphism like:
  1. Coercion
  2. Operator Overloading
  3. Polymorphic Parameters
1. Coercion:
Polymorphic coercion deals with implicit type conversion done by the compiler to prevent type errors. A typical example is seen in an integer and string concatenation.

String str="string"=15;

2. Operator Overloading:
An operator or method overloading refers to a polymorphic characteristic of same symbol or operator having different meanings (forms) depending on the context. For example, the plus symbol (+) is used for mathematical addition as well as String concatenation. In either case, only context (i.e. argument types) determines the interpretation of the symbol. 

String str = 4" + 1;
int sum = 3 + 3;
System.out.println(" str = %s\n sum = %d\n", str, sum);

Output:
str = 41
sum = 6
3. Parametric polymorphism:
allows a name of a parameter or method in a class to be associated with different types. In the below example I have defined content as a String and later as an Integer:
public class TextFile extends GenericFile{
    private String content;
    public String setContentDelimiter(){
        int content = 100;
        this.content = this.content + content;
  }
}
Note: Declaration of polymorphic parameters can lead to a problem known as variable hiding. 
Here, the local declaration of a parameter always overrides the global declaration of another parameter with the same name. To solve this problem, it is often advisable to use global references such as this keyword to point to global variables within a local context.

Comments