Last Updated on April 11, 2023 by Prepbytes
Polymorphism is a key concept in object-oriented programming, and Java is a language that fully supports it. Polymorphism allows objects of different classes to be treated as if they belong to the same class, which enables developers to write flexible and maintainable code. This article will cover runtime polymorphism in Java in detail including its definition, implementation of runtime polymorphism in Java, and benefits of runtime polymorphism in Java.
What is Runtime Polymorphism in Java?
Dynamic Method Dispatch is another name for Runtime Polymorphism in Java, which originated with the idea of method overriding. In this case, rather than at compile time, the call to an overridden method will be resolved at the moment of code execution (runtime).
The foundation of dynamic method dispatch in Java is Inheritance, which occurs when two or more classes have a parent-child relationship. Now, there might be several variations of the same method in both the parent and child classes, which are also referred to as superclass and subclasses.
It’s unclear which variation of the same method will be called. However, depending on the type of object being referred to, the Java Virtual Machine (JVM) effortlessly perceives the same during runtime.
Implementation of Runtime Polymorphism in Java
To accomplish runtime polymorphism in Java, we use method overriding. Method overriding is a technique in which a subclass adds a method that already exists in its parent class and adds new functionality to it. Thus, we can say the base class method is overridden.
The new method defined in the subclass with the same prototype as the method of the parent class but a different implementation is known as the "overriding method." The method in the parent class is referred to as the "Overridden method."
Once the method is overridden, the question remains as to how the call to this overridden method is resolved.
We typically invoke the overridden method using the reference to the base class. We’ll make a reference to the type base and then use the new keyword to create a child class object.
Thus, which method is called is determined by the contents of the reference variable or which object is referenced by the base class reference. So, if the reference objects point to a child class object, the overriding method is called. Otherwise, the overridden method is invoked if the reference object contains a base class object.
Examples of Runtime Polymorphism in Java
Let us now see some examples of how we can implement runtime polymorphism in Java.
Example – 1
Below is the code implementation and code explanation.
class Bike{ void run(){System.out.println("running");} } class Hayabusa extends Bike{ void run(){System.out.println("running safely");} public static void main(String args[]){ Bike b = new Hayabusa(); b.run(); } }
Output:
running safely
Explanation: In this example, we have a superclass Bike and a subclass Hayabusa. The Bike class has a method called run() that simply prints "running" to the console. The Hayabusa class extends the Bike class and overrides the run() method with its own implementation that prints "running safely" to the console.
In the main() method, we create an object of the Hayabusa class and assign it to a variable of type Bike. We then call the run() method on this object. Since the run() method is overridden in the Hayabusa class, Java will automatically choose the implementation of the method based on the actual type of the object at runtime. In this case, the actual type of the object is Hayabusa, so the overridden run() method in the Hayabusa class will be executed.
Example – 2
This is another example of runtime polymorphism in Java. Below is the code implementation and code explanation.
class Shape{ void draw(){System.out.println("drawing...");} } class Rectangle extends Shape{ void draw(){System.out.println("This is a rectangle...");} } class Circle extends Shape{ void draw(){System.out.println("This is a circle...");} } class Triangle extends Shape{ void draw(){System.out.println("This is a triangle...");} } class PrepBytes{ public static void main(String args[]){ Shape s; s=new Rectangle(); s.draw(); s=new Circle(); s.draw(); s=new Triangle(); s.draw(); } }
Output:
This is a rectangle...
This is a circle...
This is a triangle...
Explanation: In this example, we have a superclass Shape and three subclasses Rectangle, Circle, and Triangle. The Shape class has a method called draw() that simply prints "drawing…" to the console. Each of the subclasses overrides this method with its own implementation that prints a specific message to the console.
In the main() method, we create a variable of type Shape. We then create objects of each of the subclasses and assign them to the Shape variable. We call the draw() method on each of these objects, which will invoke the overridden version of the method from the subclass.
Benefits of Runtime Polymorphism in Java
There are several benefits of using runtime polymorphism in Java:
- Code Reusability: Runtime polymorphism in Java allows developers to reuse code from the superclass in its subclasses. This can reduce the amount of code that needs to be written and can make the code more modular and easier to maintain.
- Flexibility: Runtime polymorphism in Java allows objects of different classes to be treated as belonging to the same class. This can make the code more flexible and can make it easier to add new functionality to the code.
- Extensibility: Runtime polymorphism in Java allows developers to extend the behavior of a class by adding new subclasses that override its methods. This can make it easier to add new features to the code without modifying the existing code.
- Encapsulation: Runtime polymorphism in Java allows developers to encapsulate the implementation of a method in its subclasses. This can make it easier to change the implementation of a method without affecting the rest of the code.
- Polymorphic Parameters: Runtime polymorphism in Java allows developers to use polymorphic parameters, making it easier to write generic code that works with objects of different classes.
Conclusion
In conclusion, runtime polymorphism in Java is an important concept that enables us to write flexible and reusable code. It allows us to use the same method with different implementations, depending on the actual type of the object at runtime. This can be achieved through method overriding. By using runtime polymorphism in Java, we can write code that is easier to maintain, extend, and modify.
FAQs
Here are some frequently asked questions on runtime polymorphism in Java.
Q1: What is the purpose of runtime polymorphism in Java?
Ans: The purpose of runtime polymorphism in Java is to allow objects of different classes to be treated as if they belong to the same class, which enables developers to write flexible and maintainable code.
Q2: Who determines which method to invoke at runtime in runtime polymorphism in Java?
Ans: Java determines which method to invoke at runtime in runtime polymorphism based on the actual type of the object, rather than the declared type of the variable that holds the object.
Q3: Can runtime polymorphism in Java be achieved without inheritance?
Ans: No, runtime polymorphism in Java can only be achieved through inheritance.
Q4: What is the difference between static and dynamic binding in Java?
Ans: Static binding in Java occurs at compile-time and refers to the process of determining which implementation of a method to call based on the declared type of the variable that holds the object. Dynamic binding, on the other hand, occurs at runtime and refers to the process of determining which implementation of a method to call based on the actual type of the object.
Q5: Can a subclass override a private method in Java?
Ans: No, a subclass cannot override a private method in Java. Private methods are not visible to the subclasses.
Q6: What is the difference between compile-time polymorphism and runtime polymorphism in Java?
Ans: Compile-time polymorphism is also known as method overloading, where multiple methods have the same name but different parameters. Runtime polymorphism in Java is achieved through method overriding, where a subclass provides its own implementation of a method that is already present in the parent class.