In this tutorial, we will learn about polymorphism and its implementation with the help of examples.
This article also covers two types of polymorphism in Java: compile-time polymorphism and runtime polymorphism, as well as java polymorphism examples, method overloading, method overriding, and why polymorphism is useful in Java.
Contents
What is Polymorphism in Java?
Polymorphism in Java refers to an object’s ability to take multiple forms. To put it another way, polymorphism in Java allows us to perform the same action in multiple ways. Polymorphism is a feature of Java’s object-oriented programming language that allows a single task to be completed in multiple ways.
- In object-oriented programming, polymorphism is a crucial concept. It simply means that there are multiple forms.
- That is, in different scenarios, the same entity (method, operator, or object) can perform different operations.
- Polymorphism is a Java concept that allows us to perform a single action in multiple ways. Polymorphism is made up of two Greek words: poly and morphism. The words “poly” and “morphs” mean “many” and “forms,” respectively. As a result, polymorphism denotes the presence of multiple forms.
- Polymorphism in Java is divided into two types: compile-time polymorphism and runtime polymorphism. Polymorphism in Java is achieved through method overloading and overriding.
Example: Polymorphism
class Polygon { // method to render a shape public void render() { System.out.println("Rendering Polygon"); } } class Square extends Polygon { // renders Square public void render() { System.out.println("Rendering Square"); } } class Circle extends Polygon { // renders circle public void render() { System.out.println("Rendering Circle"); } } class Main { public static void main(String[] args) { // create an object of Square Square s1 = new Square(); s1.render(); // create an object of Circle Circle c1 = new Circle(); c1.render(); } }
Output:
Rendering Square Rendering Circle |
We’ve created a superclass, Polygon, and two subclasses, Square and Circle, in the example above. Take note of the render() method’s use.
The render() method’s main purpose is to render the shape. The process of rendering a square, on the other hand, differs from that of rendering a circle.
As a result, the render() method behaves differently depending on the class. Or, to put it another way, render() is polymorphic.
Runtime Polymorphism in Java
Dynamic Binding or Dynamic Method Dispatch are other terms for runtime polymorphism in Java. The call to an overridden method is resolved dynamically at runtime rather than at compile-time in this process. Method Overriding is used to achieve runtime polymorphism.
Method When a child or subclass has a method with the same name, parameters, and return type as the parent or superclass, that function overrides the parent’s or superclass’s function. To put it another way, if a subclass defines a method that already exists in the superclass, that function in the base class is said to be overridden.
It’s worth noting that runtime polymorphism is only possible with functions, not data members.
Overriding is accomplished by using a superclass reference variable. The object referred to by the reference variable is used to determine which method should be called. Upcasting is another term for this.
- When the parent class’s reference variable refers to the child class’s object, upcasting is used. Consider the following scenario:
class A{} class B extends A{} A a=new B(); //upcasting |
Examples of Runtime Polymorphism in Java
We’re going to make two classes in this example: Bike and Honda. Honda is an extension of the Bike class that overrides the run() method. The Parent class’s reference variable is used to call the run method. The subclass method is called at runtime because it refers to the subclass object and overrides the Parent class method.
Runtime polymorphism refers to the fact that method invocation is determined by the JVM rather than the compiler.
class Bike{ void run(){System.out.println("running");} } class Honda extends Bike{ void run(){System.out.println("Running with 40km");} public static void main(String args[]){ Bike h = new Honda();//upcasting h.run(); } }
Running with 40km |
What is Compile-Time Polymorphism in Java?
Static polymorphism is another name for compile-time polymorphism in Java. The call to the method is resolved at compile time in this process. Method Overloading is used to achieve compile-time polymorphism. Operator Overloading can also be used to achieve this type of polymorphism. Java, on the other hand, does not support Operator Overloading.
When a class has multiple methods with the same name, but the number, types, and order of parameters, as well as the return type of the methods, is different, this is known as method overloading. Java allows the user to use the same name for multiple functions as long as the type and number of parameters can be distinguished.
public class Main { public static void main(String args[]) { CompileTimePloymorphism obj = new CompileTimePloymorphism(); obj.display(); obj.display("DevelopersDome"); } } class CompileTimePloymorphism { void display() { System.out.println("Display without parameter"); } void display(String x) { System.out.println("Display with parameter" + x); } }
What is the difference between compile-time and run-time polymorphism?
One of the most important OOPs concepts is polymorphism. It is a concept that allows us to perform a single task in a variety of ways. Polymorphism is divided into two types: compile-time polymorphism and run-time polymorphism.
Compile-time polymorphism is exampled by method overloading, while run-time polymorphism is exampled by method overriding.
Sr. No. | Point | Compile-time polymorphism | Runtime polymorphism |
---|---|---|---|
1 | Basic | Compile-time polymorphism: Binding occurs at compile-time, which is referred to as polymorphism. | Run-time polymorphism, in which we know which method will be invoked at run-time. |
2 | Static/Dynamic Binding | Static binding can be used to accomplish this. | Dynamic binding can be used to accomplish this. |
3 | Inheritance | Inheritance is not involved | Inheritance is involved |
4 | Example | Compile-time polymorphism is demonstrated by method overloading. | Runtime polymorphism is demonstrated by method overriding. |
Examples of Polymorphism real Life
An individual can have a variety of relationships with various people. A woman can be a mother, a daughter, a sister, and a friend all at the same time, implying that she exhibits different behaviors in different situations.
The human body is made up of various organs. The heart is in charge of blood flow, the lungs are in charge of breathing, the brain is in charge of cognitive activity, and the kidneys are in charge of excretion. As a result, we have a standard method function that differs depending on the organ of the body.
We can achieve polymorphism in Java using the following ways:
- Method Overriding
- Method Overloading
- Operator Overloading
Java Method Overriding
Method overriding is defined as the process by which a subclass or child class has the same method as the parent class.
If the same method is present in both the superclass and the subclass during inheritance in Java. The method in the subclass then overrides the method in the superclass. This is known as method overriding.
- In this case, the same method will carry out one operation in the superclass and another in the subclass. As an example:
class Language { public void displayInfo() { System.out.println("Kotlin Language"); } } class Java extends Language { @Override public void displayInfo() { System.out.println("Java Language"); } } class Main { public static void main(String[] args) { // create an object of Java class Java j = new Java(); j.displayInfo(); // create an object of Language class Language l = new Language(); l.displayInfo(); } }
Output:
Java Language Kotlin Language |
In the preceding example, we created a superclass called Language and a subclass called Java. The method displayInfo() is present in both Language and Java in this case.
The displayInfo() function is used to print the information. It does, however, print different information in Language and Java.
Java Method Overloading
Method overloading is defined as the process of creating multiple methods with the same name in the same class, each of which works in a different way. Method overloading occurs when a class contains multiple methods with the same name.
class Shapes { public void area() { System.out.println("Find Area "); } public void area(int r) { System.out.println("Circle area = "+3.14*r*r); } public void area(double b, double h) { System.out.println("Triangle area="+0.5*b*h); } public void area(int l, int b) { System.out.println("Rectangle area="+l*b); } } class Main { public static void main(String[] args) { Shapes s = new Shapes(); // Create a Shapes object s.area(); s.area(5); s.area(6.0,1.2); s.area(7,2); } }
Output:
Find Area Circle area = 78.5 Triangle area=3.60 Rectangle area=14 |
Java Operator Overloading
Some Java operators behave differently depending on the operand. As an example:
- The + operator can perform numeric addition as well as string concatenation, and operators such as &, |, and! can perform logical and bitwise operations.
- Let’s take a look at how we can achieve polymorphism with operator overloading.
To join two entities, use the + operator. In Java, however, the + operator performs two operations.
- When the symbol + is used with numbers (both integers and floating-point numbers), it performs mathematical addition. As an example:
int a = 5; int b = 6; // + with numbers int sum = a + b; // Output = 11 |
2. When we use the + operator with strings, it performs string concatenation (join two strings). For instance:
int a = 5; int b = 6; // + with numbers int sum = a + b; // Output = 11 |
In this case, we can see that the + operator in Java is overloaded to perform two operations: addition and concatenation.
Polymorphic Variables
If a variable refers to different values under different conditions, it is said to be polymorphic.
In Java, object variables (instance variables) represent polymorphic variable behaviour. This is due to the fact that object variables of a class can refer to both objects of the class and objects of its subclasses.
Polymorphic Example
class ProgrammingLanguage { public void display() { System.out.println("Java Programming Language."); } } class Java extends ProgrammingLanguage { @Override public void display() { System.out.println("Object-Oriented Programming Language."); } } class Main { public static void main(String[] args) { // declare an object variable ProgrammingLanguage p; // create object of ProgrammingLanguage p = new ProgrammingLanguage(); p.display(); // create object of Java class p = new Java(); p.display(); } }
Output:
Java Programming Language. Object-Oriented Programming Language. |
- We created an object variable pl of the ProgrammingLanguage class in the preceding example. Pl is a polymorphic variable in this case. Because of this,
- Pl refers to the object of the ProgrammingLanguage class in the statement pl = new ProgrammingLanguage().
Furthermore, in the statement pl = new Java(), pl refers to the Java class’s object.
In Java, this is an example of upcasting.
Polymorphic Subtypes
Subtype basically means that a subtype can serve as the subtype of another type, sounds complicated?
Let us illustrate this with an example.
- Assuming we need to draw some arbitrary shapes, we can create a class called’shape’ that includes a draw() method. We will introduce an array of type’shape’ whose elements store references will refer to’shape’ subclass references by overriding draw() with other subclasses such as circle, square, rectangle, trapezium, and so on. When we call draw() again, all shapes’ draw () methods will be called.
- This Subtype polymorphism is characterised by upcasting and late binding. Upcasting is a casting that occurs when you cast up the inheritance hierarchy from a subtype to a supertype. The operator is involved in these types of casting no cast.
- We use late binding to call non-final instance methods. In short, a compiler should not perform any argument checks, type checks, method calls, or anything else, and should instead leave everything to the runtime.
The Advantages of Polymorphism in Java
- It allows the code to be reused. Classes that have been written, tested, and implemented can be reused several times. This, in turn, saves the coder a significant amount of time. Furthermore, the code can be modified without affecting the original code.
- Multiple data values can be stored in a single variable. A variable inherited from the superclass into the subclass can have its value changed without affecting the variable’s value in the superclass or any other subclasses.
- Debugging the code becomes easier for the programmer with fewer lines of code.
Polymorphism Characteristics
Other than Method Overloading and Method Overriding, polymorphism has many other characteristics. They are as follows:
- Coercion
- Internal Operator Overloading
- Polymorphic Variables or Parameters
Coercion
Coercion is concerned with the implicit conversion of one type of object into a new object of a different type. This is done automatically to avoid typing mistakes in the code.
- Value conversion from one data type to another is supported by programming languages such as C, Java, and others. There are two kinds of data type conversions: implicit and explicit.
- The programme performs implicit type conversion automatically, and this type of conversion is also known as coercion.
- To avoid type errors, for example, if one operand is an integer and the other is a float, the compiler implicitly converts the integer to a float value.
class coercion { public static void main(String[] args) { Double area = 3.14*8*8; System.out.println(area); String s = "Sagar"; int x=10; String word = s+x; System.out.println(word); } }
Output:
200.96 Sagar10 |
Internal Operator Overloading
Operator Overloading occurs when an operator or symbol behaves in more than one way depending on the input context or operand type. It is a feature of static polymorphism. Although Java does not support user-defined operator overloading in the same way that C++ does, where the user can define how an operator works for different operands, there are a few cases where Java internally overloads operators.
- The concept of operator overloading is the use of the operator of your choice. As needed, an operator symbol or method name can be used as a user-defined type.
- For example, the ‘+’ operator can be used to perform addition of numbers (of the same data type) or concatenation of two or more strings.
- When it comes to +, it can be used for both addition and concatenation.
class coercion { public static void main(String[] args) { String s = "DevelopersDome"; String s1 = "DevelopersDome1"; int x=50; int y=10; System.out.println(s+s1); System.out.println(x+y); } }
Output:
DevelopersDomeDevelopersDome1 60 |
Similarly, for logical and bitwise operations, operators such as! &, and | are overloaded. The type of argument determines how the operator is interpreted in both of these cases.
polymorphism in java, runtime polymorphism in java, types of polymorphism in java, compile time polymorphism in java,
Polymorphic Variables or Parameters
Polymorphic variables are represented in Java by object or instance variables. This is due to the fact that any class’s object variables can have an IS-A relationship with their own classes and subclasses.
- A polymorphic variable is one that can hold different types of values at the same time during execution.
- Parametric polymorphism specifies that a field name can be associated with different types during class declaration, and a method name can be associated with different parameters and return types.
class Shape { public void display() { System.out.println("Sagar Paliwal"); } } class Triangle extends Shape { public void display() { System.out.println("DevelopersDome."); } } class Main{ public static void main(String[] args) { Shape obj; obj = new Shape(); obj.display(); obj = new Triangle(); obj.display(); } }
Output:
SagarPaliwal DevelopersDome |
The obj object is a polymorphic variable in this case. This is due to the superclass’s same object referring to both the parent (Shape) and child classes (Triangle).
Issues with Polymorphism
Polymorphism has many benefits, but it also has a few drawbacks.
- Polymorphism is difficult to implement because it reduces the readability of the code.
- Polymorphism causes serious real-time performance issues.
Example: Java Runtime Polymorphism with Multilevel Inheritance
class Animal{ void eat(){System.out.println(" i am eating");} } class Dog extends Animal{ void eat(){System.out.println("i am eating fruit");} } class BabyDog extends Dog{ void eat(){System.out.println(" i am drinking milk");} public static void main(String args[]){ Animal x,y,z; x=new Animal(); y=new Dog(); z=new BabyDog(); x.eat(); y.eat(); z.eat(); } }
Output:
I am eating I am eating fruit I am drinking Milk |
You may like:
Java Inheritance with Example | Types of inheritance
Java final Keyword with Example
Hope this article will guide you to recognize all about the Java Polymorphism with example that you needed and still if you have any problem or queries regarding this, post them in the comments section and we will be glad to assist you.
Pingback: Encapsulation in Java with Example - Developers Dome
Pingback: Java enum Constructor with Example - Developers Dome
Pingback: Java enum with Example - Developers Dome
Pingback: Java Reflection with Example - Developers Dome
Pingback: Java Exception with Example - Developers Dome
Pingback: Try-with-resources in java with Example - Developers Dome