Polymorphism in OOP (Object Oriented Programming)
Polymorphism is the concept in object oriented programming in which object has different properties of its sub-classes. Object must be of generic type and its sub-classes must be inherited from it. In this context, object may have its own properties or properties of its sub-classes.
Caution! This should be clear that class may contain properties of its super-classes and not its sub-class or another class.
Polymorphism in Java
Polymorphism is related to "is-a" concept. The best way to check whether to use inheritance is "is-a" relationship. The relationship clearly describes the concept of polymorphism. Let's consider an Person class as a parent class and Student class and Employee class are inherited from this class. So, the Person class has two child classes Student and Employee. We can do following to make objects of these classes in java as shown below:
Person p = new Person();
Employee e = new Employee();
Student s = new Student();
So, what is happening under the hood is, reference variables have been pointing to objects of their respective classes.
Concept!
Person p = new Person();
Here, p is not object of class Person. In fact, p is a reference variable pointing to object of type Person. new keyword is actually creating a new object of type Person.
REFERENCE VARIABLES AND OBJECTS
To understand polymorphism, one must have understanding of reference variables and objects. So, let's go back to our previous example to understand this concept. In java, every variable has some type and p variable has type Person, e has type Employee, s has type Student. These variables are pointing to objects of their own types or classes.
IS-A Relationship
The new concept of is-relationship is coming here. So, just answer the question from below:
Person p = new Person();
From above line of code, answer that "Is Person a person?". The answer is obviously "YES". Now consider just another example where we take any other class Rectangle and do here:
Person p = new Rectangle();
"Is Rectangle a person?". The answer is obviously "NO". You whether say that in Java it is impossible and p is a reference variable of Person class and it can never point Rectangle object. In-terms of polymorphism we can say that "Rectangle is not Person".
Now, just switch to our example that Student class and Employee class extends from Person class. So, what? We can write a statement as:
Person p = new Student();
Now, it works or not. So, just use "is-a" relationship here to check the authenticity of the concept. The question is "Is student a Person?" and answer is "YES". But is this possible in java or not. So, answer is this is possible in java to do this because "each student is person".
Caution!
is-a relationship is valid only if classes inherit from parent class. If Student class does not inherit from Person class, it is illegal to show that
Person p = new Student();
So, following our previous example, let's consider another statement as below:
Person p = new Employee();
Now it's your turn to tell what is happening. Use "is-a" relationship to check whether it is legal or not is if Employee is a sub-class of Person. The question is "Is Employee a Person?" and the answer is off course "YES". So, Student and Employee both are Person. Take your time to grasp this concept and it can take time to understand this.
Before jumping to polymorphism, let's consider another example here:
Student s = new Person();
Is this statement legal or not? No, this statement is not legal because each "Person is not Student". Similar case to this statement,
Employee e = new Employee();
Creating Array of References
In Java, we can create array of references and try to understand polymorphism using this concept. Just keep in mind example of Person class and its two child classes Student and Employee. We can simply create a array of references pointing to object of type Person;
Person ref = new Person[4];
Here, we have created a array of type person that have the ability to store reference variables pointing to object of type Person. We also know that Student and Employee inherit from Person class and have also same attributes and methods of Person class. So, let's create a reference variable:
Person p1 = new Person();
ref[0] = p1;
This will be legal and allowed in java because p1 is referring to object of class Person.
But, in another case given here, if reference variable is pointing to object of sub-class, it will work or not as below:
Employee staff = new Employee();
ref[1] = staff;
Point to Note!
Private methods cannot be inherited and they belong to class only.
This will work fine but why? The answer is that staff variable is referring to object of type Employee and Employee is subclass of Person class and recall from our previous concept that "Each Employee is Person". But there is some points to consider and for this review this code below:
Below is the code of Employee class and pay attention to it:
Now, if we call methods below, what will happen,
ref[1].setSalary(50000); // ERROR
staff.setSalary(50000); // FINE
ref[1].getName(); // FINE
staff.getName(); // FINE
Now, the question is why first statement will give error because ref is a array of references of type Person and it call invoke methods of Person class but staff is referring to Employee class so it can also invoke the setSalary() method.
Concept of Dynamic Binding and Method Overriding
But here is another concept that ref[1].getName() will work correctly and works fine because there is a method in Person class getName() and staff.getName() will also work properly but the amazing thing is that both are calling the method of Employee class and string returned will be name + ":From Employee Class" and this seems to be little tricky but you will get the point soon. This is known as dynamic binding or method overriding. We will discuss this concept in detail later on.
Additional Note!
static and final methods of a parent class cannot be overridden by its sub-classes.