Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism on member variables. I know it is not possible, I don't understand this specific case

I know the behavior, but I am not 100% sure on why this occurs.
I understand that there is no polymorphism for instance variables in java. The variables are resolved statically by the compiler.
But in the following I am confused on something:

class Animal{  
   String name = "Animal";  
   public void display(){  
    System.out.println("My name is "+ name);  
   }  
}  

public class Dog extends Animal {   
   String name = "Dog";   

   public static void main(String[] args) {  
        Animal a = new Dog();  
        Dog d = new Dog();  
        System.out.println(a.name);//Line 1  
        a.display();//Line 2   
        d.display();//Line 3  
   }  
}  

I undertand that in Line 1 it will display Animal as it is the static type of a (resolved by compiler).
What confuses me is why Line 3 will also display My name is Animal?
The method will be tried to be called on Dog since this is the actual object at runtime and since it is not overidden the method will be found in the parent class Animal.
What I don't get is why the name of the parent class is used inside the method display if the actual object operated on is a Dog. Doesn't it hide the parent's name variable? It does not seem to me like it is statically resolved since the type is Dog. Isn't it part of the oject's memory layout?
It is like inside display only the parent's variable is visible. Why?

Update:

The answers by @Razvan and @LouisWasserman have been helpful.
I have 1 last question after these:
The point from both seems to be the following:
From @Razyan
System.out.println("My name is "+ this.name); //<-- note the this
From @Louis
That the this refers to Animal and that the implementation of display() is in the Animal class.

So far ok. But how are these points consistent with the fact that if I modify display() as follows:

class Animal{  
   String name = "Animal";  
   public void display(){  
    System.out.println("Current class is "+ this.getClass().getName());  
    System.out.println("My name is "+ name);  
   }  
}  

Then the result of:

 Dog d = new Dog();  
 d.display();  

Current class is Dog
My name is animal

I was expecting that this inside the display would be Animal as I understood the answers here. But it is not. Why?

like image 691
Cratylus Avatar asked Aug 20 '12 21:08

Cratylus


1 Answers

When you invoke d.display() the Animal.display() is called, since you don't override it in the Dog class.

So an imaginary implementation of Dog.display() would be something like:

 public void display(){  
    super.display();
 }

And the implementation of Animal.display() is:

 public void display(){  
    System.out.println("My name is "+ this.name); //<-- note the this
 } 

The Animal.display() method is not even aware of the existence of an object Dog and consequently of its name variable

like image 156
Razvan Avatar answered Sep 26 '22 09:09

Razvan