Java - Polymorphism Advanced
Now, lets see the total hierarchy once again.
Story :
The master God created a LivingBeing Interface and specified the rules which all the Gods has to obey.
But the Animal God faced a little problem as he was not sure which Animal makes what kind of sound(). So, he made the sound() abstract and left it to the fellow Gods to define it.
And Dog creator and Cat creator defined the sound() method by creating concrete classes(Non Abstract/All defined methods) Cat and Dog.
Dos and Don'ts for creating Objects
- LivingBeing livingBeingAnimal = new Animal(); // Cannot be done as Animal is an Abstract class.
- LivingBeing livingBeingHuman = new Human(); // This is allowed as Human is a concrete class.
- LivingBeing livingBeingDog = new Dog(); //Allowed
- LivingBeing livingBeingCat = new Cat(); //Allowed
- Animal animalDog = new Dog(); //Allowed
- Animal animalCat = new Cat(); //Allowed
- (Dog)livingBeingDog.dogRelated(); //Works fine after casting.
Now, lets take the below example and understand some of the core things of polymorphism.
Dog Class
public class Dog extends Animal{
public void sound(){
System.out.println("Dog Barks");
}
public void dogRelated(){
System.out.println("Very obidient.");
}
}
So, there are different varities of Dog. Labrador is one of them.
Story :
So, one of the Gods was given the responsibility to create Labrador. He reused the behaviours created by the Dog creator(i.e sound() and dogRelated()).
public class Labrador extends Dog{
//sound(), breathe() and dogRelated() are present by Inheritance.
public void body(){
System.out.println("They have a powerful and muscular build.");
}
public void jaws(){
System.out.println("The jaws hangs slightly and curve gracefully back");
}
}
Similarly chocolate labrador is a kind of Labrador.
Story :
So, a God was given the responsibility to create it. Naturally, he also used the behaviours of Labrador(i.e body() and jaws()).
public class ChocolateLabrador extends Labrador{
//sound(), breathe(), dogRelated(), body() and jaws() are present by Inheritance.
public void characteristics(){
System.out.println("Has a clean-cut head with broad back skull .")
}
}
Now, lets just consider the below hierarchy:
So, in the above hierarchy, class Dog has two methods, sound() & dogRelated().
Similarly, Labrador class has two methods body() & jaws(). Also it inherits all the methods
of Dog class.
And the ChocolateLabrador class has a method characteristics(). At the same time
ChocolateLabrador extends the Labrador class, inheriting all the methods of Labrador and
Dog(Since, Labrador extends Dog).
Now, let us look at the below example on polymorphism:
Class Test{
public static void main(String[] arg){
Dog dog = new Dog();
Dog dogLabrador = new Labrador();
Dog dogChocolateLabrador = new ChocolateLabrador();
(ChocolateLabrador)dogLabrador).characteristics(); // Throws ClassCastException at runtime. Labrador cannot be cast to ChocolateLabrador
((Labrador)dogLabrador).body(); // If casting not done throws compile time exception.
((ChocolateLabrador)dogChocolateLabrador).characteristics();
((Labrador)dogChocolateLabrador).body();
}
}
So, in the above example, the parent class Dog can hold a reference of Labrador class.
Dog dogLabrador = new Labrador();
Similarly, Dog class can also hold a reference of ChocolateLabrador class.
Dog dogChocolateLabrador = new ChocolateLabrador();
Now, if we try to access the characteristics() method of ChocolateLabrador class using the
Labrador reference that 'Dog dogLabrador' is holding. We end up with ClassCastException at
runtime.
(ChocolateLabrador)dogLabrador).characteristics();
That is because, being a base class, Labrador class has no idea about the methods of
ChocolateLabrador class.
In the next line 'dogLabrador' is able to access the methods of Labrador class but with
casting. Because it is the Dog reference variable 'dogLabrador' that is holding it.
((Labrador)dogLabrador).body();
Similarly, the reference variable 'dogChocolateLabrador' of Dog class can access the methods
of ChocolateLabrador class after casting. Because 'dogChocolateLabrador' is holding a reference
of ChocolateLabrador class.
((ChocolateLabrador)dogChocolateLabrador).characteristics();
Lastly, the reference variable 'dogChocolateLabrador' of Dog class is able to access the
methods of Labrador class. Even though it is holding a reference of ChocolateLabrador
class.
((Labrador)dogChocolateLabrador).body();