Java `this` 在继承情况下实际指的是什么?

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

为什么会产生以下 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 is not a true OOP language"。一点说服力都没有。

更新:private void another_print()是我的失误,我应该使用protected

在 sub-class 的打印中,您只需调用 super-class 的打印方法。 所以它当然从超级 class 打印 a

这里有两个单独的 a 字段。字段不受覆盖,只有方法可以。 super-class 有一个 a 字段,你在 sub-class 中有另一个 a 字段。

如果另一种语言产生另一种结果,那也不足为奇。另外,我不确定您的 Python 代码在逻辑上是否 equivalent/analogous 到您的 Java 代码。

是Java中构造函数调用的顺序。
SubClass 中,当您实例化 c 时,构造函数 隐式地 调用 SuperClass (public SuperClass()) 的默认构造函数(它必须这样做)。然后aSuperClass中设置为10。

现在我们已经完成了 SuperClass 构造函数,我们回到 SubClass 的构造函数,它分配 a = 20。但是 java 中的字段不受覆盖,因此 SuperClass 中的 a 仍然是 10。

之后就很明显了,我们调用c.print()调用SubClassprint,调用SuperClassprint(通过super.print()),它打印出 a,这是你记得的 10。然后 another_print(它没有被覆盖,因为它是 private)只打印出 superclass,我们'大功告成。

我的 解释了您的代码可能无法按预期工作的原因。 下面是编写的代码,您最有可能期望它的工作方式。注意代码中的注释。

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

我调试了稍微更正的代码并发现:

  1. thisSubClass
  2. 的实例
  3. 与Python不同,Java可以使用多个同名变量(如peter.petrov在他的中提到的,但我没有得到马上)
  4. 其中一个 a 来自 SubClass,第二个来自 SuperClass(作为隐式超类构造函数调用,再次不同于 Python)
  5. this.atest_super()test_sub() 中有不同的值,这就是魔法,因为 thisSubClass 和 Java 文档显示:

this is a reference to the current object — the object whose method or constructor is being called

我想我可以接受这样一个事实,即 this 将拥有整个依赖关系树中的所有变量,而 Java 将 select 根据上下文使用哪个变量。