Search code examples
javaoopinheritancetypescasting

Reasoning Behind this Java Behaviour


CONTEXT

say we have a class inheritance structure like this

class A {
    int z = 10;

    public void display() {
        System.out.println("A's z is " + z);
    }
}

class B extends A {
    int z = 20;

    public void display() {
        System.out.println("B's z is " + z);
    }

    public void onlyB() {
        System.out.println("This is only in B");
    }
}

class Main {

    public static void main(String args[]) {
        A obj = new B();

        System.out.println(obj.z); // 10
        obj.display(); // B's z is 20
    }
}

QUESTION

Why does obj.z gives A's z but obj.display() uses B's z, is there a way to think about this so that it makes sense logically?

ATTEMPTS AT UNDERTANDING

by saying

A obj = new B();

In my mind, this is saying "create an object of type A, but use al of B's implementations"

by that reasoning, it is logical that the object cannot use onlyB() because it is of type A, and A does not have onlyB(). also by that reasoning, display() would use B's implementation. But why does calling z use A's z instead of B's? shouldn't the object use B's implementation of z?

I know this wont appear in practice but I am very curious to know. A better spelled out explanation as to why this happens would be appreciated.


Solution

  • In Java (and most languages I know), fields are not overriden. So if you define a field in parent class and other field in child class with same name, both fields will exists there (and each one can be accessed normally within its class). (Consider defining your z in B as String not int! now they have different types, and B sees a String z).

    But non-static methods can be overriden.

    When you have A obj = new B() you are having an instance of B, but with a reference of type A. When accessing the fields (which are not overridable), then your are accessing A.z, but when you call the method (which is overriden), the real method which is called lookup through a dynamic lookup table and B's method get called (that's the power of inheritance), and the method accesses it's own z. (Again consider z in B be of String, then obj.z is of type int not String which is in the obj's type class).