Superclass reference not able to call subclass method in Java
I have a basic doubt in polymorphism in Java. I have written the code below in one file named AnimalTestDrive.java. According to me the code below should work specially the line in bold but unfortunately its not. Can you please explain why, I have given the error below:
class Dog extends Animal {
public void dogMethod() {
System.out.println("In Dog method");
}
}
public class AnimalTestDrive {
public static void main(String args[]) {
Dog d = new Dog();
d.dogMethod();
d.animalMethod();
Animal animal = new Animal();
animal.animalMethod();
animal = d;
**animal.dogMethod(); // THIS IS NOT WORKING**
}
}
Solution 1:
Let's try to look at this line the same way that the compiler would:
animal.dogMethod();
First, it needs to work out what animal
means. That's nice and easy - it's a local variable in the current method, so it doesn't need to look far.
The compile-time type of that variable is Animal
. The compiler doesn't care what the value of the variable will be at execution time - it only uses the information about the declared type.
So, that's what it uses to try to look up what dogMethod()
means within the context of animal
, i.e. with type Animal
. First it looks in Animal
, then in java.lang.Object
(the implicit superclass of Animal
) - but neither of those classes contains a declaration of dogMethod
. At that point, the compiler has to give up with an error - it can't find the method. It doesn't matter that the method is available on the execution-time type of the object that the value that animal
refers to. It has to bind it at compile-time, using only the information available at compile time.
The only decision made at execution time is which implementation of a method is used - for example, if you called animal.toString()
and the Dog
class had an override, e.g.
@Override public String toString() {
return "I'm a dog";
}
then the compiler would find the toString()
method from java.lang.Object
, so it would know that the method call was valid - but the implementation in Dog
would be used because of the execution-time type of the object.
Solution 2:
As far as Java can tell, animal is just an animal, so it can only do the things defined in your Animal class. If you want to be able to use the Dog method, and you know your animal is a Dog, you have to cast it to a Dog for the method to be visible.
In other words, the only methods and fields available for a variable are the ones defined by it's left hand side type. You can either say ((Dog)animal).dogMethod()
; to refer to animal as a Dog, or create a new variable Dog animalAsDog = animal;
and call your method on animalAsDog.