Runtime Polymorphism in Java

polymorphism in java, now its time to dig a bit deeper into it. There are two types of Polymorphism which is possible in Java, Runtime Polymorphism (Dynamic Binding) and Compile time Polymorphism (Static Binding). Lets take a look into it one by one.

Runtime Polymorphism(Dynamic Binding)

Method Overriding in Java is the best example for Runtime Polymorphism. In this type of Polymorphism the Parent class reference can hold object of Parent class or any sub class(Child class) of Parent. This technique is called as Dynamic Method Dispatch

//Assigning Parent class Object to Parent class reference Parent p = new Parent(); //Assigning Child class Object to Parent class reference Parent p = new Child();
Upcasting

If the reference variable of Parent class refers to the object of Child class, it is known as upcasting.

Upcasting in java
class A{} class B extends A{}
A a=new B();//upcasting

For upcasting, we can use the reference variable of class type or an interface type

interface I{} class A{} class B extends A implements I{}

Here, the relationship of B class would be:

B IS-A A B IS-A I B IS-A Object
Example of Java Runtime Polymorphism

In this example, we are creating two classes Bike and Splendor. Splendor class extends Bike class and overrides its run() method. We are calling the run method by the reference variable of Parent class. Since it refers to the subclass object and subclass method overrides the Parent class method, the subclass method is invoked at runtime.

Since method invocation is determined by the JVM not compiler, it is known as runtime polymorphism.

class Bike{ void run(){System.out.println("running");} } class Splendor extends Bike{ void run(){System.out.println("running safely with 90km");} public static void main(String args[]){ Bike b = new Splendor();//upcasting b.run(); } }


Output:
running safely with 90km.
Java Runtime Polymorphism Example: Bank

Consider a scenario where Bank is a class that provides a method to get the rate of interest. However, the rate of interest may differ according to banks. For example, SBI, ICICI, and AXIS banks are providing 8.4%, 7.3%, and 9.7% rate of interest.

Java Runtime Polymorphism example of bank
Note: This example is also given in method overriding but there was no upcasting.
class Bank{ float getRateOfInterest(){return 0;} } class SBI extends Bank{ float getRateOfInterest(){return 9.5f;} } class ICICI extends Bank{ float getRateOfInterest(){return 8.4f;} } class AXIS extends Bank{ float getRateOfInterest(){return 7.3f;} } class TestPolymorphism{ public static void main(String args[]){ Bank b; b=new SBI(); System.out.println("SBI Rate of Interest: "+b.getRateOfInterest()); b=new ICICI(); System.out.println("ICICI Rate of Interest: "+b.getRateOfInterest()); b=new AXIS(); System.out.println("AXIS Rate of Interest: "+b.getRateOfInterest()); } }


Output:
SBI Rate of Interest: 9.5 ICICI Rate of Interest: 8.4 AXIS Rate of Interest: 7.3
Java Runtime Polymorphism Example: Shape
class Shape{ void draw(){System.out.println("drawing...");} } class Rectangle extends Shape{ void draw(){System.out.println("drawing rectangle...");} } class Circle extends Shape{ void draw(){System.out.println("drawing circle...");} } class Triangle extends Shape{ void draw(){System.out.println("drawing triangle...");} } class TestPolymorphism2{ public static void main(String args[]){ Shape s; s=new Rectangle(); s.draw(); s=new Circle(); s.draw(); s=new Triangle(); s.draw(); } }


Output:
drawing rectangle... drawing circle... drawing triangle...
Java Runtime Polymorphism Example: Animal
class Animal{ void eat(){System.out.println("eating...");} } class Dog extends Animal{ void eat(){System.out.println("eating bread...");} } class Cat extends Animal{ void eat(){System.out.println("eating rat...");} } class Lion extends Animal{ void eat(){System.out.println("eating meat...");} } class TestPolymorphism3{ public static void main(String[] args){ Animal a; a=new Dog(); a.eat(); a=new Cat(); a.eat(); a=new Lion(); a.eat(); }}


Output:
eating bread... eating rat... eating meat...
Java Runtime Polymorphism with Data Member

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

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

Rule: Runtime polymorphism can't be achieved by data members.
class Bike{ int speedlimit=80; } class Honda3 extends Bike{ int speedlimit=120; public static void main(String args[]){ Bike obj=new Honda3(); System.out.println(obj.speedlimit);//90 }


Output:
80
Java Runtime Polymorphism with Multilevel Inheritance
class Animal{ void eat(){System.out.println("eating");} } class Dog extends Animal{ void eat(){System.out.println("eating fruits");} } class BabyDog extends Dog{ void eat(){System.out.println("drinking milk");} public static void main(String args[]){ Animal a1,a2,a3; a1=new Animal(); a2=new Dog(); a3=new BabyDog(); a1.eat(); a2.eat(); a3.eat(); } }


Output:
eating eating fruits drinking Milk

Dynamic Method Dispatch is a technique in which the overriden method to call is resolved at the run-time rather than at compile time. In this technique we will assigning the Child object to the Parent class reference.

class Parent { public void display(String name) { System.out.println("Welcome to Parent Class \""+name+"\""); } public void disp() { System.out.println("disp() method of Parent class"); } } public class Child extends Parent { public void display(String name) { System.out.println("Welcome to Child Class \""+name+"\""); } public void show() { System.out.println("show() method of Child class"); } public static void main(String args[]) { //Assign Child Object to Parent class reference Parent pp = new Child(); pp.display("PR"); } }


Output:
Welcome to Child Class "PR"

Here we have assigned Child class object (new Child()) to Parent class reference (Parent pp) and now come the question which of the display() method will be called. Here the new Child() object is resolved in the run-time the display() method of the child class will be called and hence the output will be

What if the child class didn’t override the parent class method?

In the above example of Dynamic Method Dispatch the child class has overriden the parent class display() method and hence the child class display() method is called, now the question is what will happen if the child class didn’t override the parent class method.

class Parent { public void display(String name) { System.out.println("Welcome to Parent Class \""+name+"\""); } public void disp() { System.out.println("disp() method of Parent class"); } } public class Child extends Parent { public void show() { System.out.println("show() method of Child class"); } public static void main(String args[]) { //Assign Child object to Parent class reference Parent pp = new Child(); pp.display("PR"); } }


Output:
Welcome to Parent Class "PR"
Can the Child class method be called in the Dynamic Method Dispatch?
class Parent { public void display(String name) { System.out.println("Welcome to Parent Class \""+name+"\""); } public void disp() { System.out.println("disp() method of Parent class"); } } public class Child extends Parent { public void display(String name) { System.out.println("Welcome to Child Class \""+name+"\""); } public void show() { System.out.println("show() method of child class"); } public static void main(String args[]) { //Assign Child refernce to Parent class Parent pp = new Child(); pp.show(); } }


When you run the above code then we will get the below compile time exception “The method show() is undefined for the type Parent”. In Dynamic Method Dispatch

  1. The Overridden methods of the Child class can be called.

  2. Non-Overridden methods of the Parent class can be called.

  3. Child class methods cannot be called.

Compile time Polymorphism (Static Binding)

Method overloading in Java is the best example for Compile time Polymorphism. In Complie time Polymorphism the control flow is decided during the compile time itself. Simply we can say that a class can have more than one method with a same name but difference in the parameters. Lets look into the below code for the better understanding.

class A { public void disp() { System.out.println("Inside First disp method"); } public void disp(String val) { System.out.println("Inside Second disp method, value is: "+val); } public void disp(String val1,String val2) { System.out.println("Inside Third disp method, values are : "+val1+","+val2); } } public class B { public static void main (String args[]) { A a = new A(); a.disp(); //Calls the first disp method a.disp("Java Interview"); //Calls the second disp method a.disp("JavaInterview", "Point"); //Calls the third disp method } }


Output:
Inside First disp method Inside Second disp method, value is: Java Interview Inside Third disp method, values are : JavaInterview,Point

As we can see in the above example class A have 3 disp() methods but the number and type of parameter differs. In this scenario the compiler will be able to figure out which disp() method to call during the compile time itself based on number and type of parameter and hence it is called as Compile time Polymorphism.




Instagram