Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java inconsistent inheritance mechanics?

I think we already discussed this issue in this post here Inheritance in Java simple clarification

But since the example here is a bit simpler and the point i want to be clarified is different i´ll give it a shot.

First, the two classes to discuss:

public class SuperClass{
    SuperClass() {
        foo();
    }

    public void foo() {
        System.out.println("Super.foo()");
    }

    public static void main(String[] args) {
            SuperClass tn = new DerivedClass();
            tn.foo();
    }
}

public class DerivedClass extends SuperClass{
    String i;

    TrickyB() {
        i = "aksjhdf";
    }

    public void foo() {
        System.out.println("In derived.foo() --> " + i);
    }
}

I (at least I think) understand the concepts of polymorphism and i know why DerivedClass.foo() is called when invoking

new DerivedClass();

I see an inconsistency here:

At the time we invoke the c´tor of DerivedClass the c´tor of the SuperClass is called implicitly (so to say as the first line of the Derived c´tor).

So in the Super c´tor, DerivedClass is not fully initialised, which makes working with this class useless. This point is reflected in the output of this program

In derived.foo() --> null
In derived.foo() --> aksjhdf

The first line reflects my confusion:

Why is DerivedClass.foo() called? The object is not ready yet, so doing anything with it is nonsense in my eyes.

Can anyone explain the reasons to me. I think this absolutely counter intuitive.

BTW: I would have expected SuperClass.foo() to be called, since, as I said, it doesnt make any sense to work with an "unready" object.

On the other Hand: As I think of it. It doesn´t make any sense to me neither, that, while I´m in the c´tor of SuperClass, DerivedClass.foo() is called!

How would I call SuperClass.foo() in my case?

like image 757
Tomas Longo Avatar asked Jan 18 '26 23:01

Tomas Longo


2 Answers

Why is DerivedClass.foo() called? The object is not ready yet, so doing anything with it is nonsense in my eyes.

No. The object has already been created. Constructors don't create objects, it just initializes them. The object is created by new operator here.

I would have expected SuperClass.foo() to be called

As already explained, it's not that object is not created. It's already been. And that invocation will call the overridden method. That is why you should never call overridden method from constructor. You'll see unexpected behaviour.

SuperClass does not know anything about any derived classes.

Well, it doesn't need to know. The fact that the method invocation invokes the derived class method has nothing to do with whether superclass knows about subclass or not. The actual method that will be invoked is decided at runtime, based on the actual object in picture. Since here, the object is of type DerivedClass, the method in the DerivedClass if present will be invoked.

How would I call SuperClass.foo() in my case?

You don't. That's the whole point. Go through the post that I linked for step-by-step explanation.

like image 124
Rohit Jain Avatar answered Jan 20 '26 15:01

Rohit Jain


Unlike C++, Java sets the runtime type of the object at the time of allocation, before any constructor is run. This is why polymorphic behavior occurs during initialization.

This behavior can be useful sometimes, under controlled circumstances. In most cases, however, it's a good idea to avoid it, because you are leaking an uninitialized object to code that is external to your class (via the this reference in the virtual method). You should try only calling private (or final) methods from the constructor, whenever possible.

like image 22
Theodoros Chatzigiannakis Avatar answered Jan 20 '26 16:01

Theodoros Chatzigiannakis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!