wmock
wmock

Reputation: 5492

Understanding Java's inheritance model

Example code:

public class Parent {
  String name = "Parent";

  public String getName() {
    return this.name;
  }
}

public class Child extends Parent {
  String name = "Child";

  public String getName() {
    return this.name;
  }
}

public class Tester {
  public static void main (String[] args) {
    Parent p = new Child();
    Child  c = new Child();
    System.out.println("p.name is " + p.name); // prints out "Parent"
    System.out.println("c.name is " + c.name); // prints out "Child"
    System.out.println("p.getName() is " + p.getName()); // prints out "Child"
    System.out.println("c.getName() is " + c.getName()); // prints out "Child"
  }
}

My Understanding So Far

So far, my understanding of inheritance in Java allows me to understand why the 3rd and 4th println statements produce "Child" as an output. At compile time, the compiler makes sure that getName method is defined in the type of the reference variable but during runtime is when which version getName is determined. And since both reference variables actually refer to a Child object, Child's getName is invoked.

Question 1

However, why is it that when you access the instance variable directly, the behavior is different from how methods are accessed? In particular, I find it strange that p.name returns "Parent" instead of "Child".

Question 2

In a similar vein, if I commented out the getName function in the Child class and re-ran the code in Tester, I'm surprised to see that p.getName() and c.getName() return "Parent" instead of "Child".

Can someone help elaborate on these 2 questions?

Upvotes: 3

Views: 107

Answers (1)

Thirler
Thirler

Reputation: 20760

Variables can not be overridden in Java. What you have done is called hiding a variable (the variable name in Parent is difficult to access)

The way to understand the behavior you are describing is to think of name as only the name of the variable, not an actual variable. When used in the context (in terms of code, not actual type of a variable) of Parent it points to a different variable than when used in the context of Child.

When calling c.name or p.name you tell the program which context to use, because the variables c and p are declared respectively of type Child and Parent. When using it in a method inside the class the variable of the current class is used.

If you want to use the Parent.name in a child class you will have to cast it:

System.out.println("c.name is " + ((Parent) c).name);

For a method, the function called is always that of the actual type of the variable being called. In your case, regardless of calling it from Tester, Parent or Client.

Of course it is best not to hide variables at all, an use different names for different variables.

Upvotes: 4

Related Questions