AchillesVan
AchillesVan

Reputation: 4356

Inheritance : Unexpected Output from return statement

I am taking a practice test for Java certification and got this question:

What will the following code print?

class Baap {

    public int h = 4;

    public int getH() {
        System.out.println("Baap    "+h);
        return h;
    }  
}  

class Beta extends Baap {

    public int h = 44;

    public int getH() {
        System.out.println("Beta    " + h);
        return h;
    } 

    public static void main(String[] args) {  
        Baap b = new Beta();  
        System.out.println(b.h + "    " + b.getH());  
        Beta bb = (Beta) b;  
        System.out.println(bb.h + "   " + bb.getH());  
    }  
}  

This is the answer:
Beta 44 4 44
Beta 44 44 44

My question: why is the 4 from the main class returned instead of the 44 from child class? Shouldn't it return 44?

I also don't see any variable that is shadowed by another variable with the same name that is closer in scope.

(Sorry for my english. I am French speaking.)

Upvotes: 1

Views: 197

Answers (2)

NPE
NPE

Reputation: 500663

So your question is why b.h evaluates to 4 and not 44 in the following:

    Baap b = new Beta();  
    System.out.println(b.h + "    " + b.getH());  
                       ^^^ why is this 4?

The reason is that there is no data polymorphism in Java. Even though they share the same name, Baap.h and Beta.h are separate, unrelated fields.

When the compiler is resolving b.h it looks at the static (i.e. compile-time) type of b, not its dynamic (i.e. runtime) type.

The static type of b is Baap, so b.h resolves to Baap.h, which is 4.

Upvotes: 2

Unihedron
Unihedron

Reputation: 11051

This is because Beta.h and Baap.h are different fields. In b.h, Baap.h is called (which is 4) and bb.h, Beta.h is called (which is 44). The difference is that b.getH() calls Beta.getH() (because b is new Beta()) but is reading Baap.h field, while bb.getH() calls Beta.getH().

Take a look at the main() method:

class Baap {  
    public int h = 4;  
    public int getH() { System.out.println("Baap    "+h); return h; }  
}  

class Beta extends Baap {
    public int h = 44;
    public int getH() { System.out.println("Beta    "+h); return h; }

    public static void main(String[] args) {
        Baap b = new Beta();
        System.out.println(b.h + "    " + b.getH());
        /* The string concatenation gets compiled to:
         * new StringBuffer().append(b.h).append("    ").append(b.getH()).toString();
         *                             \ This is Baap.h         \ This prints Beta 44 and returns 44 from Beta.h
         */
        // Printed "Beta 44" from b.getH().
        // Printed "4    44" from statements concatenation.
        Beta bb = (Beta) b;  
        System.out.println(bb.h + "   " + bb.getH());
        /* The string concatenation gets compiled to:
         * new StringBuffer().append(bb.h).append("    ").append(bb.getH()).toString();
         *                             \ This is Beta.h          \ This prints Beta 44 and returns 44 from Beta.h
         */
        // Printed "Beta 44" from b.getH().
        // Printed "44    44" from statements concatenation.
    }
}

From the Oracle JavaTM Tutorials - Inheritance, it was written that:

What You Can Do in a Subclass

  • The inherited fields can be used directly, just like any other fields.
  • You can declare a field in the subclass with the same name as the one in the superclass, thus hiding it (not recommended).
  • You can write a new instance method in the subclass that has the same signature as the one in the superclass, thus overriding it.
  • You can declare new fields in the subclass that are not in the superclass.

Read more:

Upvotes: 2

Related Questions