Ajinkya Ronghe
Ajinkya Ronghe

Reputation: 13

Can someone please explain this Java upcasting behavior I am little confused?

In the code given below when we are trying to initiate object of type A by calling the constructor of a child class when we print x.i java refers to the parent class attribute and why when called through a method it refers to a child class attribute, I am unable to clearly understand how upcast is working here.

Following is the code:

public class Main
{
    public static void main(String[] args) {
        A x = new B();
        System.out.println(x.i);
        System.out.println(x.shout());
    }
}

class A{
    int i = 10;
    int shout(){
        return i;
    }
}

class B extends A{
    int i = 20;
    int shout(){
        return i;
    }
}
Following is the output:
10
20

Upvotes: 1

Views: 88

Answers (3)

Andreas Lundgren
Andreas Lundgren

Reputation: 12545

This is because methods in Java are overridden when redefined in a child class, but attributes are shadowed. Thus there will only be one method shout() available, but there are two actual attributes i.

In a real case scenario, you would probably define your attributes private if you would need to use the same name. Then you would explicitly handle to choose which one you want to access using getters (like shout() that pretty much is a getter for i). Or at least explicitly point out what i by casting to the right class. If you still want to shadow a public attribute with another having the same name, you can still refer to them as super.i or this.i to select the right one.

Upvotes: 2

WJS
WJS

Reputation: 40047

You assigning an instance of B to A so you are using B's overridden method which also uses B's instance field of i when calling the method. It is similar to a closure in that it encapsulates B's version of i. When accessing A's version of i directly, you get A's version which, from A's perspective is not shadowed.

If you wanted to access A's version of i from B's shout() method you could do the following:

class B extends A{
    int i = 20;
    int shout(){
        return super.i;
    }
}

Using your current invocations you would get

10
10

There is a lot more to this. For more information check out Inheritance, Overriding, and Hiding in the Java Language Specification.

Upvotes: 1

KpekepSalt
KpekepSalt

Reputation: 54

When child class has a field with the same name as a superclass's field it is called - Hiding a field. Java does not support polymorphism for fields.

So in your example overridden method will be invoked and as a result child's field will be used. But when accessed directly through parent class, parent's field will be used.

public class Main
{
    public static void main(String[] args) {
        A x = new B();
        System.out.println(x.i); // Uses A.i
        System.out.println(x.shout()); // Uses B.shout()
    }
}

Upvotes: 1

Related Questions