为什么可以重写方法但不能重写属性?

14

我有一个班级

public class A {
    public String attr ="A attribute";
    public void method() {
        System.out.println(this+" , "+this.attr);
    }
    public String toString() {
        return("Object A");
    }
}

以及另一个继承自它的类

public class B extends A{
    public String attr = "B attribute";
    public void method() {
        super.method();
    }
    public String toString() {
        return("Object B");
    }
}
注意,Bmethod() 只是 Amethod() 的一个包装器。
当我运行以下代码时:
B b = new B();
b.method();

我得到对象B,A属性作为输出,这意味着thisthis.attr访问了不同的东西。为什么会这样?

System.out.println(this)不应该引用类AtoString()方法吗?


1
现代的集成开发环境(IDE)将有可能在第二个attr的定义上显示一个警告,提示它“遮蔽”了超类中同名的字段。 - Mark Jeronimus
@Noah,你为什么要恢复编辑后的问题名称呢?我认为编辑后的标题“为什么可以重写方法而不能重写属性”比现在的更能描述问题的内容。这对于所有寻找答案的其他人来说都很重要。 - Ondra K.
1个回答

13

当你声明一个与父类同名的方法时,你会覆盖它,也就是替换原有的行为。但是如果你声明了一个同名字段,你实际上是隐藏它,让它在子类中无法访问,只能通过super.field访问。请参阅Oracle文档中关于变量隐藏的说明,以及使用关键字super。请注意,不建议使用变量隐藏,因为它会导致你现在遇到的混淆。

通过调用super.method(),在打印this时会调用toString方法,而这个方法实际上已被重写 - 这就是为什么它打印出"Object B"的原因,因为你在B类的实例上调用了该方法。但是this.attr中的this实际上指的是父对象,因为你正在通过super.method()从父类调用method


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接