The Wizard
The Wizard

Reputation: 953

Java method overriding and variable shadowing

public class Circle {
    public float r = 100;
    public float getR() {
        return r;
    }
}

public class GraphicCircle extends Circle {
    public float r = 10;
    public float getR() {
        return r;
    }

    // Main method
    public static void main(String[] args) {
        GraphicCircle gc = new GraphicCircle();
        Circle c = gc;
        System.out.println("Radius = " + gc.r);
        System.out.println("Radius = " + gc.getR());
        System.out.println("Radius = " + c.r);
        System.out.println("Radius = " + c.getR());
    }

}

Hi, I am having trouble understanding the output of the code above. The output is:

Radius = 10.0
Radius = 10.0
Radius = 100.0
Radius = 10.0

I understand why gc.r is 10. I also understand why gc.getR() is 10 (because the getR() method in the GraphicCircle overrides the getR() method of Circle). But I don't understand why c.r is 100, and c.getR() is 10 (I am having trouble understanding what happens in inheritance when you typecast to an ancestor class as the code has done above).

Upvotes: 9

Views: 2297

Answers (3)

Seelenvirtuose
Seelenvirtuose

Reputation: 20658

First of all, the field r is not shadowed, it is hidden.

Second, the technical term in respect to overriding methods is called dynamic binding. That simply means that at runtime the actual class of the instance is being consulted when looking up the method that is being called.

On the other hand, for fields we have static binding. That means that the compiler already resolves all field accesses, and the compiler only knows about declared types.

So the conclusion is:

System.out.println("Radius = " + c.r);

This prints 100.0 as the variable is of type Circle, so the compiler writes the access to field Circle.r into the byte code.

Upvotes: 4

Advicer
Advicer

Reputation: 1330

You can override methods, not fields or class variables. So getR() is overridden and it actually displays what you're expecting.

Getting c.r you access circle's class variable and not GC's.

It also a bad habit to make class variables public. They should be private or at least protected and accessed them using getters and setters (more about private fields).

Upvotes: 7

Michał Kosmulski
Michał Kosmulski

Reputation: 10020

Method calls are virtual in Java, which means that the method from an object's actual type is called, regardless of what type the reference was which you used to access the object. Direct field access on the other hand is not virtual, so which r you access will depend on the type of the reference through which you reached it.

Upvotes: 8

Related Questions