Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance and Object Creation

Base Class:

public class Inheritance {
    int i;
    Inheritance() {
        System.out.println("I am in base class" + i);
    }
}

Derived Class:

public class TestInheritance extends Inheritance {

    TestInheritance() {
        System.out.println("I am in derived class");
    }

    public static void main(String[] args) {
        TestInheritance obj = new TestInheritance();        
    }
}

This is what I have in mind regarding what is going on above.

When I create an object of the derived class by default super() is called and the constructor of the base class is called and it initializes the variable i.

Now, my question is: Does the constructor in this case only initialize the variable i and doesn't create a concrete object of class?

From what I have read so far there is only one object created - of the derived class which has i variable in it.

But from the time the constructor of base class is called and the point in time where constructor of the derived class is called how/where is i stored in memory?

And what would be the case in which base class is an abstract one.

I would really appreciate if I can know what happens in memory at different points of time.

If I have said something which is fundamentally incorrect please let me know. I really want to know how this thing works.

like image 708
Prateek Avatar asked Aug 22 '13 22:08

Prateek


2 Answers

Physically you created a single object, but conceptually you created 2. It's like when, say, a baby girl is born: physically she is only one, but conceptually a new female has been born, also a new human being has been born, a new sentient being has been born, a new inhabitant of planet Earth has been born, etc. Yes, exactly. There is a relationship of inheritance (subTyping) here too, and I did it on purpose. To avoid confusion, it's probably better to say that there is only one object with several facets; one object that is member of different (super-)classes at the same time.

Now, said enough about the logical part, let's examine the physical part. The single (physical) object is created with the following structure in memory

+--------------------------+----------------------------+
|             B            |              C'            +
+--------------------------+----------------------------+

The first part (B) contains all fields inherited from the superclass B of C (if any). The second part (C', and I'm using ' for "complement") contains all fields that are "proprietary" of C (i.e. are not being inherited from B but defined in C itself). It is important to note that the created object does not start on C', but on B. It is the combination of the inherited fields with the new fields what makes up the full object.

Now, if B had had its own superclass A, the structure would have been like this:

+--------+-----------------+----------------------------+
|    A   |      B'         |              C'            +
+--------+-----------------+----------------------------+

What is important to note here is that B == A + B'. In other words, C doesn't need to know about A. All it cares is its immediate superclass B, which hides its internal structure.

To answer the specific questions:

Does the constructor in this case only initialize the variable i and doesn't create a concrete object of class?

In the same way that A, B, and C above were structurally chained, they are also chained during initialization. If it weren't this way, it's like the girl in my original example had been born without being any of the other things we know she also is by definition. It's impossible. A complete contradiction. So, the construction process of both classes is carried out, which includes: initializing fields in a "zero" value (null for references and false for boolean's), and executing one constructor (which can call other constructors).

In this particular case, field i is initialized, an Inheritance constructor is executed, TestInheritance's fields (if it had had any) would have been initialized, and then a TestInheritance's constructor would have been executed. How can we tell exactly what constructors of each class? Relatively simple. What initiated everything is new TestInheritance(). This is obviously indicating that TestInheritance's constructor that doesn't have any parameter (which exists; otherwise there would be a compilation error). However, this constructor is not explicitly invoking any constructor of the superclass (through the keyword super(...)). As we saw above, this can not be, and the compiler automatically inserts the equivalent to super(), i.e. a call to the superclass's constructor without arguments (Inheritance()). Again, this constructor exists, and everything is good. Output would have been:

I am in base class 0
I am in derived class

Constructors with no parameters are called "default constructors" for 3 main reasons: - They usually are very simple as they don't have parameters. - They are called automatically when the constructor of a subclass does not explicitly call any supeclass constructor. - They are provided automatically for those classes without any constructor explicit written by the programmer. In this case the constructor does nothing, and only initialization takes place.

From what I have read so far there is only one object created - of the derived class which has i variable in it.

This is not entirely correct. Physically, it's true that only one object was created, but it corresponds to the class used with new (TestInheritance), which in this case happens to have no fields, but this is irrelevant. In fact, both output lines are printed. Conceptually... well we already mentioned this.

But from the time the constructor of base class is called and the point in time where constructor of the derived class is called how/where is i stored in memory?

When new TestInheritance() is executed, the first thing that happens, before constructors are called, even before initialization is performed, is that memory is allocated for the whole object. - Usually this memory is "dirty" and that's why it needs to be initialized. - There is space for TestInheritance's fields, its superclass' fields, and so on. Even the position of each field within the object in memory is know in advance.

So, even before the constructor of base class is called there is already memory allocated for i and any other field, just that they are "dirty" (not initialized).

And what would be the case in which base class is an abstract one.

There is no difference. The only one is that you can't create objects of an abstract class by themselves. You create them as part of a (concrete) subclass. This is similar to the fact that a new human being can not be born by him/herself. It's either a baby girl or a baby boy.

I would really appreciate if I can know what happens in memory at different points of time.

I hope I did.

If I have said something which is fundamentally incorrect please let me know. I really want to know how this thing works.

Nothing "fundamentally incorrect".

like image 150
Mario Rossi Avatar answered Oct 02 '22 18:10

Mario Rossi


I think this is a common area of confusion over inheritance. You seem to have grasped that only one object is created, that's correct.

I recommend that you think of the instance variables in the base class as being contained in any superclass as well, just as any public or protected method in the base class is accessible from the superclass.

When an object is instantiated, the java runtime does what it needs to do to allocate storage for all the things that storage is needed for -- mostly instance variables. So the instance variable in the base class can be thought of as being part of a block of memory that contains all the instance variables for the object, whether they are declared in the subclass or the superclass.

And one terminology correction: in your code, the variable is not "initialized" explicitly -- I think what you mean to ask about is "allocation", i.e., at what point does the variable have its space in memory. "Initialize" implies that the variable has been given a value, and although Java is very good about assigning default values to its variables, I think you men allocation in this case.

like image 36
arcy Avatar answered Oct 02 '22 18:10

arcy