0

Excuse me for my ignorance. The following code outputs

A1 has name A1
B1 has name A1

But I am expecting

A1 has name A1
B1 has name B1

as String name is redefined in the sub-class. Can anyone explain?

Code Snippet:

public class Client {
    public static void main(String[] args) {
        A1 a = new A1();
        A1 b = new B1();

        System.out.println(a.greeting() + " has name " + a.getName());
        System.out.println(b.greeting() + " has name " + b.getName());
    }
}


class A1 {
    String name = "A1";

    String getName() {
        return name;
    }

    String greeting() {
        return "class A1";
    }
}


class B1 extends A1 {
    String name = "B1";

    String greeting() {
        return "class B1";
    }
}
  • I haven't downvoted because you included your complete code. But, it's typically good form to do some research for the answer and if you can't find the answer then ask your question and show what research you've already done. – Mabdullah Apr 23 '14 at 14:17
  • Instance variables are not polymorphic. – GriffeyDog Apr 23 '14 at 14:30
  • please see the links in my answer @GriffeyDog is correct, you can't override the name variable you'll want to use accessors and private variables instead, the second link (from SO) has an example of this. – Mabdullah Apr 23 '14 at 14:43

3 Answers3

2

By declaring a variable in your subclass with the same name as a variable declared in a parent class, you're hiding the variable in the parent class. The variable in the child class is a different variable than the variable with the same name in the parent class. You might try something like this:

class B1 extends A1 {
    public B1(){
       name = "B1";
    }

    String greeting() {
        return "class B1";
    }
}
Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
  • I understand that I am shadowing the variable name. But, what I am thinking is that B1 has getName() and the JVM while invoking the method should use B1's name instead of A1's. –  Apr 23 '14 at 14:15
  • Then what you are thinking is incorrect. You could add a getName() function to B1 that returns the name variable from the B1 class, but then what's the point of extending A1? – Kevin Workman Apr 23 '14 at 14:17
  • I think the reason is that the method invocation of getName() on b is not polymorphic method invocation. It is compile time binding. –  Apr 23 '14 at 14:25
1

You don't override getName, so the one from B1 uses A1 implementation, which returns a field name from A1 and has no access to name in B1. As stated before, this is called variable hiding.

undefined
  • 1,354
  • 1
  • 8
  • 19
0

Here is an Oracle JavaDoc that explains overriding and hiding with Java in more details.

http://docs.oracle.com/javase/tutorial/java/IandI/override.html

also see this SO article, about overriding Java instance variables

Is there a way to override class variables in Java?

I think this should help explain why this is happening, it primarily has to do with how you are instantiating your variables.

Community
  • 1
  • 1
Mabdullah
  • 1,013
  • 6
  • 26