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
.
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.
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.
My comment explained the reason your code probably doesn't work as expected. Below is code written how you most likely expected it to work. Note the comments in the code.
static class SuperClass {
int a; // only declare field in superclass to avoid hiding
public SuperClass() {
this.a = 10;
}
// make method protected, public, or package private to allow children to override it
protected void another_print() {
System.out.println("superclass");
}
public void print() {
System.out.println(this.a);
this.another_print();
}
}
static class SubClass extends SuperClass {
public SubClass() {
this.a = 20;
}
@Override
protected void another_print() {
System.out.println("subclass");
}
public void print() {
super.print();
}
}
public static void main (String[] args) {
SubClass c = new SubClass();
c.print();
}
This will print
20
subclass
I've debugged my slightly corrected code and found out that:
this
is an instance of SubClass
a
s is from the SubClass
and the second is from the SuperClass
(as implicit superclass constructor call, again unlike Python) this.a
has a different value in test_super()
and test_sub()
and that is the magic, given that this
is a SubClass
and Java documentation reads:
this
is a reference to the current object — the object whose method or constructor is being called
I think I can live with the fact that this
will have all the variables from the whole dependency tree and Java will select which one to use depending on the context.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.