繁体   English   中英

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不是真正的OOP语言”。 根本不是很有说服力。

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

在子类的打印中,您只需调用超类的打印方法。 所以它当然从超级类打印出来的。

这里有两个单独字段。 字段不受覆盖,只有方法。 超类有一个字段 ,你有另一个在子类中的字段。

如果另一种语言产生另一种结果,那不是一个大惊喜。 此外,我不确定您的Python代码在逻辑上是否等同于/类似于您的Java代码。

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

现在我们已经完成了SuperClass构造函数,我们回到SubClass的构造函数,它指定a = 20 但字段不受制于Java的重写,所以aSuperClass仍是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. 与Python不同,Java可以使用多个同名变量(如他的答案中提到的peter.petrov,但我没有马上得到它)
  3. 其中a来自SubClass ,第二个来自SuperClass (作为隐式超类构造函数调用,再次与Python不同)
  4. this.a有不同的值test_super()test_sub()这是神奇的,因为this是一个SubClass和Java文件内容如下:

this是对当前对象的引用 - 正在调用其方法或构造函数的对象

我认为我可以忍受这样一个事实: this将包含整个依赖树的所有变量,Java将根据上下文选择使用哪一个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM