Let's take this simple Java code:
public class Animal {
public void eat() {
System.out.println("Generic Animal Eating Generically");
}
}
public class Horse extends Animal {
public void eat() {
System.out.println("Horse eating hay ");
}
public void eat(String s) {
System.out.println("Horse eating " + s);
}
}
I'm trying to figure out which version of the three eat() methods will run. Now, when I type
Animal a = new Animal();
a.eat();
The output is "Generic Animal Eating Generically", which is completely understandable.
The same thing happens when I type:
Horse h = new Horse();
h.eat();
The output is "Horse eating hay", which is, again, completely logical.
Here's where it gets confusing for me though. When I type:
Animal ah = new Horse();
ah.eat();
I get:
Horse eating hay
I expected the compiler to invoke the eat() method from the Animal class reference, not the Horse object reference.
So my question is, how can I know for sure which method the compiler is going to invoke when I have a generic reference variable types referring to an object type (like this one: Animal horse = new Horse();
This is called dynamic binding in Java. The explicite object type is used not the reference type.
It is not possible to call the overriden super method and the overriding method using a single method, see: How to call the overridden method of a superclass. You could add a method to your horse, which delegates the call to the animal like:
This is happens because of method overriding. In method overriding, the reference type does not matter, it is the object type that matters.
Animal ah
is simply a reference to the object and the actual object is of typeHorse
. So,Horse
's method will be called instead of reference typeAnimal
's method.Ohkay, new keyword will create instance of given class...
Now Horse class already is a child of Animal. So following will be instantiate.
Now you are trying to store that object in Animal's object. It means Object Of Horse is stored in Animal's Object.
So in Animal's object member of Horse is already stored. That is the reason that compiler is printing child class method values.
Let's correct this statement first. The variable
ah
is a reference of typeAnimal
and the statementnew Horse()
creates an instance of typeHorse
and assigns it to anAnimal
reference.Now that the terminologies are clear, this behavior is expected and is termed as runtype-polymorphism or dynamic method dispatch. At compile time,
eat()
is resolved based on the reference type which is of typeAnimal
, but at runtime, the method that will be called is based on the instance type which isHorse
.You could follow these simple steps :
ah.eat()
is calling the methodeat
.Animal ah = new Horse()
, the reference type isAnimal
that is the parent classAnimal ah = new Horse()
, the instance type isHorse
which is the child class.If all the above conditions are satisfied, you are looking at runtype polymorphism and the method from the child class will be called. In any other scenario, the method to be called will be resolved based on the reference type.
It would also pay to understand that a child class inherits methods from its parents. Lets say that you delete the
public void eat()
method fromHorse
class, you are no longer Overrding theeat()
method; however, thepublic void eat(String s)
method inHorse
is still said to Overload the inheritedeat
method fromAnimal
. Next, lets add apublic void eat(String s)
method inAnimal
. With this addition, you are now Overloading theeat
method inAnimal
and Overrding it inHorse
class. No matter how you change the code, the 4 steps mentioned above will always help you decide which method will be called.