在扩展 Java 中另一个类的类中具有 2 个同名的变量

2022-09-02 12:42:44

以下是我的项目代码的一部分:

public class Body extends Point{
    public double x, y, mass;

    public Body() {
        x = y = mass = 0;
    }

    public Body(double x, double y, double mass) {
        this.mass = mass;
        this.x = x;
        this.y = y;
    }
}

public class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

我很快意识到,这样做将在 Body 类中创建个名为 x 的变量,在 Body 中创建另外两个名为 y 的变量。这怎么可能,为什么Java甚至允许这样做?

我假设这是类 Body 的正确代码:

public class Body extends Point{
    public double mass;

    public Body() {
        super();
        mass = 0;
    }

    public Body(double x, double y, double mass) {
        super(x,y);
        this.mass = mass;
    }
}

感谢您抽出宝贵时间接受采访


答案 1

从某种意义上说,您正在覆盖超类的字段。但是意外地这样做要容易得多,因为没有重载字段(您只有一个给定名称的变量,类型无关紧要)。这称为变量“隐藏”或“阴影”。所以,你是对的,你最终会得到两个同名的字段。

您的第二个示例是正确的。它们是从超类继承的,并且由于它们未声明为私有,因此它们对子类可见。直接引用超类的字段通常是不好的做法,除非有充分的理由,否则它们应该声明为私有。调用超级构造函数的示例是最佳方法。

另外,如果您隐藏了具有另一个同名字段的字段,您仍然可以将它们称为super.x,super.y,vs. this.x,this.y,如果可能的话,您应该避免这种情况。


答案 2

是的,您将有两个变量,其中一个隐藏另一个。允许它有意义,原因有两个:

  1. 假设你有一个基类和一个派生类,作者对此一无所知。的作者是否应该因为派生类可能共享字段而永远无法添加任何字段?或者,当更改为 实际上并不影响正确性时,应该停止编译?BaseDerivedBaseBaseDerivedBase
  2. 您的字段应几乎总是私有的,此时名称是否重复并不重要 - 任何一方都不会知道另一方的变量。