Java`this`在继承情况下实际指的是什么?
为什么以下Java代码会产生:Java`this`在继承情况下实际指的是什么?,java,oop,inheritance,constructor,this,Java,Oop,Inheritance,Constructor,This,为什么以下Java代码会产生: 10 superclass 有关守则是: class SuperClass { int a; public SuperClass() { this.a = 10; } private void another_print() { System.out.println("superclass"); } public void print() { System.ou
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();
}
}
从来没有创建过超类的实例,不是吗?
Java不仅开始寻找从超类调用的方法,它甚至不知何故知道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()
是我的错误,我应该在子类的print中使用protected
您只需调用super类的print方法。
当然,它会打印超级类中的a
这里有两个独立的a字段。字段不受重写的约束,只有方法被重写。超级类有一个a字段,您在子类中有另一个a字段
如果另一种语言产生了另一种结果,这并不奇怪。另外,我不确定您的Python代码在逻辑上是否与Java代码等效/类似 这是Java中构造函数调用的顺序。
在子类
中,当实例化c
时,构造函数隐式调用超类
(公共超类()
)的默认构造函数(它必须这样做)。然后a
在超类中被设置为10
现在我们已经完成了超类
构造函数,我们回到子类
的构造函数,它分配a=20
。但是字段在java中不受重写的约束,因此超类中的a
仍然是10
很明显,我们调用c.print()
,它调用子类的print
,它调用超类的print
(bysuper.print()
),它打印a
,就像你记得的那样。然后另一个\u print
(由于它是private
,所以不会被覆盖)只打印超类
,我们就完成了。My解释了代码可能无法按预期工作的原因。
下面是您最可能期望它如何工作的代码。注意代码中的注释
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
我调试了稍加修改的代码,发现:
此
是子类
与Python不同,Java可以使用多个相同名称的变量(正如peter.petrov在他的文章中提到的,但我没有马上得到它)
其中一个a
s来自子类,第二个来自超类(作为隐式超类构造函数调用,同样与Python不同)
this.a
在test\u super()
和test\u sub()
中有一个不同的值,考虑到this
是一个子类,Java文档如下所示:
此
是对当前对象的引用,即调用其方法或构造函数的对象
我想我可以接受这样一个事实,这个
将包含整个依赖关系树中的所有变量,Java将根据上下文选择要使用的变量。不一样。python没有私有方法。您不能重写超类方法,因为它是私有的。变量a也被隐藏,因为这两个类都声明了它。您可以自由地告诉您的同事Java也不是纯OOP语言(Python可能是,尽管其他人可能知道得更好)。这与所指的内容无关,而是编译器如何解析方法调用和字段名。我习惯于在Java中包含@Override
注释,即使它不是必需的。当某些内容没有被正确覆盖时,编译器会抱怨