☰
Polymorphism is an object-oriented programming concept that refers to the ability of a variable, function or object to take on multiple forms. A language that features polymorphism allows developers to program in the general rather than program in the specific.
As an example, let us assume there is a base class named Animals from which the subclasses Horse, Fish and Bird are derived. Let us also assume that the Animals class has a function named Move, which is inherited by all subclasses mentioned. With polymorphism, each subclass may have its own way of implementing the function. So, for example, when the Move function is called in an object of the Horse class, the function might respond by displaying trotting on the screen. On the other hand, when the same function is called in an object of the Fish class, swimming might be displayed on the screen. In the case of a Bird object, it may be flying.
In effect, polymorphism trims down the work of the developer because he can now create a sort of general class with all the attributes and behaviors that he envisions for it. When the time comes for the developer to create more specific subclasses with certain unique attributes and behaviors, the developer can simply alter code in the specific portions where the behaviors will differ. All other portions of the code can be left as is.
Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.
Polymorphism is the process of exhibiting multiple actions with only one interface. Infact everything around us exhibit polymorphism in one way or another.
The best example is the GOOGLE Search Engine. There is just one search Textbox which you can use to search for everything. You can search for "Wolverine 2013 movie" or "Objective Questions on Core Java" and it would present the related pages. There is NO SEPARATE SEARCH BOX for each category and thus "One Interface multiple Actions"!!
In object-oriented programming, polymorphism refers to a programming language's ability to process objects differently depending on their data type or class. More specifically, it is the ability to redefine methods for derived classes.
Any Java object that can pass more than one IS-A test is considered to be polymorphic. In Java, all Java objects are polymorphic since any object will pass the IS-A test for their own type and for the class Object.
It is important to know that the only possible way to access an object is through a reference variable. A reference variable can be of only one type. Once declared, the type of a reference variable cannot be changed.
The reference variable can be reassigned to other objects provided that it is not declared final. The type of the reference variable would determine the methods that it can invoke on the object. A reference variable can refer to any object of its declared type or any subtype of its declared type. A reference variable can be declared as a class or interface type.
Let us look at an example.
public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}
Now, the Deer class is considered to be polymorphic since this has multiple inheritance. Following are true for the above example:
When we apply the reference variable facts to a Deer object reference, the following declarations are legal:
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;
All the reference variables d,a,v,o refer to the same Deer object in the heap.
Real-world example
Polymorphism is essentially considered into two versions:
[1] Compile time polymorphism (static binding or method overloading)
[2] Runtime polymorphism (dynamic binding or method overriding)
In this, method to be invoked is determined at the compile time. Compile time polymorphism is supported through the method overloading concept.Method overloading means having multiple methods with same name but with different signature (number, type and order of parameters).
In simple terms we can say that a class can have more than one methods with same name but with different number of arguments or different types of arguments or both.
In method overloading, an object can have two or more methods with same name, BUT, with their method parameters different. These parameters may be different on two basis:
[1] Parameter type: Type of method parameters can be different. e.g. java.util.Math.max() function comes with following versions:
public static double Math.max(double a, double b){..}
public static float Math.max(float a, float b){..}
public static int Math.max(int a, int b){..}
public static long Math.max(long a, long b){..}
The actual method to be called is decided on compile time based on parameters passed to function in program.
[2] Parameter count: Functions accepting different number of parameters. e.g. in employee management application, a factory can have these methods:
EmployeeFactory.create(String firstName, String lastName){...}
EmployeeFactory.create(Integer id, String firstName, String lastName){...}
Both methods have same name 'create' but actual method invoked will be based on parameters passed in program.
class X
{
void methodA(int num)
{
System.out.println ("methodA:" + num);
}
void methodA(int num1, int num2)
{
System.out.println ("methodA:" + num1 + "," + num2);
}
double methodA(double num) {
System.out.println("methodA:" + num);
return num;
}
}
class Y
{
public static void main (String args [])
{
X Obj = new X();
double result;
Obj.methodA(20);
Obj.methodA(20, 30);
result = Obj.methodA(5.5);
System.out.println("Answer is:" + result);
}
}
Output:
methodA:20
methodA:20,30
methodA:5.5
Answer is:5.5
As you can see in the above example that the class has three variance of methodA or we can say methodA is polymorphic in nature since it is having three different forms. In such scenario, compiler is able to figure out the method call at compile-time that's the reason it is known as compile time polymorphism.
[Note]:Another term operator overloading is also there, e.g. '+' operator can be used to add two integers as well as concat two sub-strings. Well, this is the only available support for operator overloading in java, and you can not have your own custom defined operator overloading in java.
Here are the rules which you keep in mind while overloading any method in java:
public class DemoClass {
// Overloaded method
public Integer sum(Integer a, Integer b) {
return a + b;
}
// Overloading method
public Integer sum(Float a, Integer b) { //Valid
return null;
}
}
public class DemoClass {
// Overloaded method
public Integer sum(Integer a, Integer b) {
return a + b;
}
// Overloading method
public Float sum(Integer a, Integer b) { //Not valid; Compile time error
return null;
}
}
public class DemoClass {
// Overloaded method
public Integer sum(Integer a, Integer b) throws NullPointerException{
return a + b;
}
// Overloading method
public Integer sum(Integer a, Integer b) throws Exception{ //Not valid; Compile time error
return null;
}
}
In this, the method to be invoked is determined at the run time. The example of run time polymorphism is method overriding. When a subclass contains a method with the same name and signature as in the super class then it is called as method overriding.
Declaring a method in subclass which is already present in parent class is known as method overriding.
Method overriding, in object oriented programming, is a language feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes. The implementation in the subclass overrides (replaces) the implementation in the superclass by providing a method that has same name, same parameters or signature, and same return type as the method in the parent class. The version of a method that is executed will be determined by the object that is used to invoke it. If an object of a parent class is used to invoke the method, then the version in the parent class will be executed, but if an object of the subclass is used to invoke the method, then the version in the child class will be executed. Some languages allow a programmer to prevent a method from being overridden.
Method overriding is a perfect example of runtime polymorphism. In this kind of polymorphism, reference of class X can hold object of class X or an object of any sub classes of class X. For e.g. if class Y extends class X then both of the following statements are valid:
Y obj = new Y();
//Parent class reference can be assigned to child object
X obj = new Y();
Advantage of method overriding
The main advantage of method overriding is that the class can give its own specific implementation to a inherited method without even modifying the parent class(base class)
Let's see what problem we may face in the program if we don't use method overriding.
class Animal{
void run(){
System.out.println("Animal is running");
}
}
class Tiger extends Animal{
}
class Demo{
public static void main(String args[]){
Tiger obj = new Tiger();
obj.run();
}
}
Output:
Animal is running
But I want to provide a specific implementation of run() method in subclasses. For that reason we go for method overriding.class Animal{
void run(){
System.out.println("Animal is running");
}
}
class Tiger extends Animal{
void run(){
System.out.println("Tiger is running");
}
}
class Demo{
public static void main(String args[]){
Tiger obj = new Tiger();
obj.run();
}
}
Output:
Tiger is running
Since in method overriding both the classes(base class and child class) have same method, compile doesn't figure out which method to call at compile-time. In this case JVM(java virtual machine) decides which method to call at runtime that's why it is known as runtime or dynamic polymorphism.
Lets see some examples to understand method overriding better.
public class X
{
public void methodA() //Base class method
{
System.out.println ("hello, I'm methodA of class X");
}
}
public class Y extends X
{
public void methodA() //Derived Class method
{
System.out.println ("hello, I'm methodA of class Y");
}
}
public class Z
{
public static void main (String args []) {
X obj1 = new X(); // Reference and object X
X obj2 = new Y(); // X reference but Y object
obj1.methodA();
obj2.methodA();
}
}
Output:
hello, I'm methodA of class X
hello, I'm methodA of class Y
As you can see the methodA has different-2 forms in child and parent class thus we can say methodA here is polymorphic.
Lets have one more example.
public class Animal {
public void makeNoise()
{
System.out.println("Some sound");
}
}
class Dog extends Animal{
public void makeNoise()
{
System.out.println("Bark");
}
}
class Cat extends Animal{
public void makeNoise()
{
System.out.println("Meow");
}
}
Now which makeNoise() method will be called, depends on type of actual instance created on runtime e.g.
public class Demo
{
public static void main(String[] args) {
Animal a1 = new Cat();
a1.makeNoise(); //Prints Meow
Animal a2 = new Dog();
a2.makeNoise(); //Prints Bark
}
}
Output:
Meow
Bark