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

时间:2016-01-12 22:12:12

标签: 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.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

4 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:8)

这是用Java调用的构造函数的顺序 在SubClass中,当您实例化c时,构造函数隐式调用SuperClasspublic 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)

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

  1. thisSubClass
  2. 的一个实例
  3. 与Python不同,Java可以使用多个同名变量(如answer中提到的peter.petrov,但我没有马上得到它)
  4. 其中一个a来自SubClass,第二个来自SuperClass(作为隐式超类构造函数调用,再次与Python不同)
  5. this.atest_super()test_sub()中有不同的值,这是神奇的,因为thisSubClass并且Java文档读取:< / LI>
      

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

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