为什么以下Java代码会产生:
10
superclass
有问题的代码是:
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();
}
}
没有创建SuperClass
的实例,不存在?
不仅Java开始寻找从SuperClass
调用的方法,它甚至以某种方式知道a = 10
!
让我们考虑类似的Python代码:
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()
它按预期工作:
20
subclass
我的同事(Python不喜欢Java人员)提出的唯一解释是:“Python不是真正的OOP语言”。根本不是很有说服力。
更新:private void another_print()
是我的错误,我应该使用protected
。
答案 0 :(得分:8)
在子类的打印中,您只需调用超类的打印方法。 所以它当然会从超级类打印 a 。
此处有两个单独的 a 字段。字段不受覆盖,只有方法。超类有一个 a 字段,你在子类中有另一个 a 字段。
如果另一种语言产生另一种结果,那并不是什么大惊喜。此外,我不确定您的Python代码在逻辑上是否等同于/类似于您的Java代码。
答案 1 :(得分:8)
这是用Java调用的构造函数的顺序
在SubClass
中,当您实例化c
时,构造函数隐式调用SuperClass
(public SuperClass()
)的默认构造函数(必须这样做) )。然后a
中的SuperClass
设置为10。
现在我们已经完成了SuperClass
构造函数,我们回到了SubClass
的构造函数,它指定了a = 20
。但是字段不受java覆盖,因此a
中的SuperClass
仍为10.
之后很明显,我们致电c.print()
调用print
的{{1}},SubClass
调用print
SuperClass
({{1} }}),打印super.print()
,这是你记得的那样10.然后a
(因为它是another_print
而没有被覆盖)只打印private
而我们已经完成了
答案 2 :(得分:2)
我的comment解释了您的代码可能无法按预期工作的原因。 下面是代码,写下你最有可能期望它如何工作。请注意代码中的注释。
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();
}
这将打印
20
subclass
答案 3 :(得分:0)
我调试了稍微纠正过的代码并发现了:
this
是SubClass
a
来自SubClass
,第二个来自SuperClass
(作为隐式超类构造函数调用,再次与Python不同)this.a
在test_super()
和test_sub()
中有不同的值,这是神奇的,因为this
是SubClass
并且Java文档读取:< / LI>
醇>
this
是对当前对象的引用 - 正在调用其方法或构造函数的对象
我认为我可以接受这样一个事实:this
将拥有整个依赖关系树中的所有变量,而Java将根据上下文选择使用哪一个。