1

I have tried to do some research on how Subclasses are able to access the methods and fields of the Superclasses. When I read a post on stackoverflow that explained how inheritance 'really' works, I was confused to see my output. The post I read was: What really happens on inheritance in Java?

After having read this post, this is my understanding on inheritance which I ask you to correct if wrong:

  • Methods and fields are not copied to the subclass, but are instead called from a Superclass object unless overridden in a Subclass. I have confirmed methods and fields not being copied to the subclass by using the javap command.
  • When calling a method in a Subclass, it looks during runtime for the method in the Subclass object (a possible overriding method) and if it is not found it will go up in hierarchy to find it in a Superclass object and then call it from a Superclass object.
  • Because methods and fields are not copied to the Subclass but are instead called from a Superclass object, the Subclass constructor calls super(); implicitly to make sure there's a Superclass object available to call inherited methods from.

Applying the logic I just wrote down, I came across some weird outputs. In the example below I have class A (Superclass) and class B (Subclass). I received B as output from the Main method but was instead expecting A as output.

Class A:

public class A {
    public void getTheClass() {
        System.out.println(getClass().getSimpleName());
    }
}

Class B:

public class B extends A {
    public B() {
        getTheClass();
    }

}

Class Main:

public class Main {
    public static void main(String[] args) {
        B b = new B();
    }
}

The reason why I expected A as output, is because (according to the earlier described logic) the getTheClass() method will be called from the Superclass object (A) as the Subclass object (B) does not have a method named getTheClass(). The Subclass object does not have this method because according to my understanding, methods and fields are not copied to Subclasses.

If the Subclass does not have this method, it will go up in hierarchy to search for an object that does and call it from there, which in this case would be the Superclass object (A). So if the getTheClass() method is called from the Superclass object (A), wouldn't the class of the object be class A rather than class B? And in that case, why did it not output A but instead B? I get the same confusing result if I print out the keyword this.

John
  • 33
  • 3
  • [`getClass()`](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#getClass--) returns the runtime class of the object. – Robby Cornelissen Sep 27 '18 at 04:25
  • Adding to what others have said, getClass() is itself inherited from the Object base class in java. So by your reasoning getClass wouldn't have returned A but would have returned Object. – LonelyCpp Sep 27 '18 at 04:29
  • You have constructed class B [ new B() ], class A is just sharing its fields and methods to its children. To have it output class A, you will need to construct A. – alhinai-hamed Sep 27 '18 at 04:29

1 Answers1

1

Because it goes up in hierarchy when a called method is not found in a Subclass object, the Subclass constructor calls super(); implicitly to make sure there's a Superclass object available to call inherited methods from.

The constructor (in the child and parent) will be invoked when you create the object itself and not when you invoke methods on an object (as you need a fully constructed object for invoking methods on it).

The reason why you don't see the printed class name as A is that the getClass() method returns the runtime type of the object (which is B)

From javadoc, (emphasis mine)

Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.

Reference:

What is a "runtime class" in Java?

Thiyagu
  • 17,362
  • 5
  • 42
  • 79
  • Yes my bad, I made a typo there. Can you please explain me how this ''runtime type of an object'' works and causes my code to not output A? I do not really understand the difference between the runtime type and what I understand now. – John Sep 27 '18 at 04:29
  • @John https://stackoverflow.com/questions/40486720/what-is-a-runtime-class-in-java – LonelyCpp Sep 27 '18 at 04:33
  • When you have `A ob = new B()` or `B ob = new B()`, you are having an object of type `B` (which is also assignable to a reference to of type `A` since all `B`s are `A`s). The runtime type here is the actual object that is created which is `B` here.. (also note to create a `B`, the constructor of `A` will be called. You can verify this by writing a default constructor in `B` and `A` see the order in which they are called). – Thiyagu Sep 27 '18 at 04:33
  • But in my example, I am creating an object A (with a implicit super call) and an object B. On runtime, because the getTheClass() is not defined in object B, it uses getTheClass() from object A. So if it would do A.getTheClass(), isn't the runtime class in this case A? – John Sep 27 '18 at 12:40
  • No. You are not creating an object of type `A` and also the runtime type is `B`. Think about this - if the runtime type is `A` how can you access the fields and methods on `B` (if that object is not of type `B`). Only the method in `A` gets called, but the actual type is `B` – Thiyagu Sep 27 '18 at 14:32
  • But the constructor in class B implicitly calls Super(); does this not create an object of type 'A'? I would indeed understand it if getTheClass(); was called from object 'B' but because methods are not copied over to Subclasses, object 'A' only has this method. And my understanding is that because it could not find the method in object B, it will look for the method in object 'A'. That results in calling A.getTheClass(). It could be that my understanding of how methods and properties are inherited is just wrong that causes this confusion. – John Sep 27 '18 at 14:48
  • It does not create an object of A. Methods are also not copied over as you said. `And my understanding is that because it could not find the method in object B, it will look for the method in object 'A'.` - there are no two objects (there is just one here which is `B`). Class `B` has the methods in `A` plus anything extra that it declares. – Thiyagu Sep 27 '18 at 14:51
  • First of all I'd like to thank you User7 for your fast reply, and please bear with me as I try to understand. Anyways, if class 'B' has the methods of 'A', aren't they copied from Subclass A to Subclass B? And what is the point of calling Super() then? And if 'B' has the methods of 'A', then why did javap not show it – John Sep 27 '18 at 14:52
  • You need to call super to initialize the fields in the superclass (which is needed to construct a B). TBH, I don't know how this(maybe a lookup table sort of thing is maintained I guess) is done by the JVM internally – Thiyagu Sep 27 '18 at 14:55
  • So if I am correct: You are saying that it's not getting copied because there was never an object 'A' created in the first place to copy from? The object 'B' during creation gets the methods and fields from the Superclass (which is kinda copying from the Superclass). And for that reason you are saying that when I call the getTheClass() method, it will do B.getTheClass() as object B received (copied) this method from class 'A' during creation? – John Sep 27 '18 at 15:01
  • This should answer you https://stackoverflow.com/questions/9005851/does-an-instance-of-superclass-get-created-when-we-instantiate-an-object – Thiyagu Sep 27 '18 at 15:14
  • Thank you so much User7.. I have spent literally over 10 hours trying to understand this concept. You have no idea howmuch you've helped me. . I've been stuck on this subject for so long and not being able to move on because it was all so confusing for me. All along I have thought that two objects were created. I thought that 'Super();' was creating an object, but there was never a 'new' keyword involved and therefore it was only calling the constructor to initialize the fields in object B that were inherited from the Superclass. – John Sep 27 '18 at 15:57