8

Possible Duplicate:
The concept of shadowing

I am confused about how the fields of classes are handled in Java during upcasting. For example:

class SuperClass
{
    String myString = "String in SuperClass";

    public void myMethod()
    {
        System.out.println("Method in SuperClass");
    }
}

class SubClass extends SuperClass
{
    String myString = "String in SubClass";

    public void myMethod()
    {
        System.out.println("Method in SubClass");
    }
}

class Question
{
    public static void main(String[] args)
    {
        SuperClass test = new SubClass();
            // object test is an instance of SubClass
            // but I am telling the compiler to treat it as SuperClass

        test.myMethod();
        System.out.println(test.myString);

    }
}

Output:

Method in SubClass
String in SuperClass //Why is "String in SubClass" not used?

When I create an object test it is an instance of SubClass class; however, I am telling the compiler to treat it as SuperClass. Everything is clear to me about methods work: I will only be able to use the methods of the SubClass, if a given method is defined for SuperClass.

However, I am lost as to why a field of a SuperClass is used when I try to access myString of test. Since test is an instance of SubClass I would expect myString defined in SubClass to be used, why is this not happening? What am I missing?

I know that I can access, myString of SubClass by using this operator. For example, I could define printMyString method in SuperClass, and overwrite it with

public void printMyString()
{
    System.out.println(this.myString);
}

In the SubClass, so my question is mostly about how come the field of the SuperClass is used in test. Maybe I am missing something obvious?

I tried to search for the answer, and the closest topic I found was Upcasting in Java and two separate object properties, though helpful, it did not answer my question.

Thank You in Advance

Community
  • 1
  • 1
Akavall
  • 82,592
  • 51
  • 207
  • 251

2 Answers2

7

Attributes cant be overloaded like methods.

test.myMethod(); 

Here method invocation depends on the type of actual object. Here object is of type SubClass so method of SubClass is invoked.

test.myString

While accessing attributes,it depends on the type of reference variable. Here reference variable ie test is of type SuperClass so attribute from SuperClass is accessed.

What you are looking is class variable hiding / shadowing.

Ajinkya
  • 22,324
  • 33
  • 110
  • 161
  • Nice link, thank you. The key part is: "When an instance variable in a subclass has the same name as an instance variable in a super class, then the instance variable is chosen in the class that is the reference type." – Akavall Jan 01 '13 at 07:05
  • @Akavall: Ya you hit the point :) – Ajinkya Jan 01 '13 at 07:26
5

Fields in Java are only hidden and not actually overridden (that doesn't mean that we'll get a compile time error while trying this, instead they are not overridden in its true sense).

Overriding means the member should be invoked based on the run time type of the object and not based on the declared type.

But binding for fields in Java is always static and hence it's based on the declared type of the object reference only.

In the example you've given, by declaring the class variable with the name 'myString' in class SubClass you hide the class variable it would have inherited from its superclass SuperClass with the same name 'myString'.

Java language specification :

If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class.

A hidden field can be accessed by using a qualified name if it is static, or by using a field access expression that contains the keyword super or a cast to a superclass type.

Community
  • 1
  • 1
Rahul
  • 15,979
  • 4
  • 42
  • 63