Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does Java `this` actually refer to in an inheritance situation?

Why does the following Java code produces:

10
superclass

The code in question is:

class SuperClass {
    int a;

    public SuperClass() {
        this.a = 10;
    }

    private void another_print() {
        System.out.println("superclass");
    }

    public void print() {
        System.out.println(this.a);
        this.another_print();
    }
}

class SubClass extends SuperClass {
    int a;

    public SubClass() {
        this.a = 20;
    }

    private void another_print() {
        System.out.println("subclass");
    }

    public void print() {
        super.print();
    }
}

public class Main {
    public static void main (String[] args) {
        SubClass c = new SubClass();
        c.print();
    }
}

There is no instance of SuperClass ever created, isn't there? Not only that Java starts looking for the method to invoke from the SuperClass, it even somehow knows that a = 10!

Let's consider a similar Python code:

class SuperClass:
    def __init__(self):
        self.a = 10

    def another_prn(self):
        print('superclass')

    def prn(self):
        print(self.a)
        self.another_prn()

class SubClass(SuperClass):
    def __init__(self):
        self.a = 20

    def another_prn(self):
        print('subclass')

    def prn(self):
        super().prn()

c = SubClass()
c.prn()

It works as I expect:

20
subclass

The only explanation that my colleagues (Python disliking Java folks) came up with is: "Python is not a true OOP language". Not very convincing at all.

Update: private void another_print() is my blunder, I should have used protected.

like image 321
Kirill Avatar asked Jan 12 '16 22:01

Kirill


2 Answers

It is the order of constructor calling in Java.
In the SubClass, when you instantiate c, the constructor implicitly calls the default constructor of the SuperClass (public SuperClass()) (it must do so). Then a is set to be 10 in the SuperClass.

Now that we're done with the SuperClass constructor, we get back to the constructor of SubClass, which assigns a = 20. But fields are not subject to overriding in java, so a in SuperClass is still 10.

After that it's pretty obvious, we call c.print() which calls the print of SubClass, which calls the print of SuperClass (by super.print()), which prints a which is as you remember 10. Then another_print (which is not overridden since it is private) just prints superclass and we're done.

like image 192
Idos Avatar answered Sep 27 '22 20:09

Idos


In the sub-class's print you just call super-class's print method. So it prints the a from the super class of course.

You have two separate a fields here. Fields are not subject to overriding, only methods are. The super-class has an a field and you have another a field in the sub-class.

If another language produces another result, that's not a big surprise. Also, I am not sure your Python code is logically equivalent/analogous to your Java code.

like image 39
peter.petrov Avatar answered Sep 27 '22 21:09

peter.petrov