简体   繁体   English

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

[英]Having 2 variables with the same name in a class that extends another class in Java

Following is a part of my code for a project: 以下是我的项目代码的一部分:

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;
    }
}

I quickly realized that doing this will create two variables inside the Body class called x and two other variables in Body called y. 我很快意识到这样做会在Body类中创建两个名为x的变量,在Body中创建另外两个名为y的变量。 How is this even possible, and why on earth does Java even allow it? 这怎么可能,以及为什么Java甚至允许它呢?

I assume this is the correct code of class Body: 我假设这是类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;
    }
}

Thanks for your time 谢谢你的时间

In a sense, you are overriding fields of the super class. 从某种意义上说,你是超越超级阶级的领域。 But it's far easier to do accidentally because there is no overloading of fields (you only have one variable of a given name, the type doesn't matter). 但是由于没有字段超载(你只有一个给定名称的变量,类型无关紧要),因此意外地做起来要容易得多。 This is referred to as variable 'hiding' or 'shadowing'. 这被称为变量'隐藏'或'阴影'。 So, you're correct, you'll end up with two fields with the same name. 所以,你是对的,你最终会得到两个同名的字段。

Your second example is correct. 你的第二个例子是正确的。 They are inherited from the super-class and since they are not declared private, they are visible to the subclass. 它们是从超类继承的,因为它们不是私有的,所以它们对子类是可见的。 It's generally bad practice to refer directly to a super-class's fields, and unless there is good reason, they should declared private. 直接引用超类的字段通常是不好的做法,除非有充分的理由,否则它们应该被声明为私有。 Your example of invoking the super constructor is the best approach. 调用超级构造函数的示例是最好的方法。

Also, if you hide a field with another of the same name, you can still refer to them as super.x, super.y, vs. this.x, this.y, you should avoid this situation if at all possible. 此外,如果您使用同名的另一个字段隐藏字段,您仍然可以将它们称为super.x,super.y,而不是this.x,this.y,如果可能的话,您应该避免这种情况。

Yes, you'll have two variables, with one hiding the other. 是的,你将有两个变量,一个隐藏另一个。 It makes sense to allow it for two reasons: 允许它有两个原因:

  1. Suppose you've got a base class Base and a derived class Derived which the author of Base has no idea about. 假设你有一个基类Base和派生类DerivedBase的作者根本不知道。 Should the author of Base never be able to add any fields, just because a derived class might share the fields? Base的作者是否应该能够添加任何字段,只是因为派生类可能共享字段? Or should Derived stop compiling when the change to Base doesn't actually affect the correctness? 或者,当对Base的更改实际上不影响正确性时, Derived是否应该停止编译?
  2. Your fields should almost always be private, at which point it doesn't matter whether the names are duplicated or not - neither "side" will know about the variables of the other. 你的字段几乎总是私有的,此时名称是否重复并不重要 - “side”都不会知道另一个的变量。

Further to what others have said: Is Body a Point ? 继其他人所说的: Body是一个Point吗? No, Body has a position property of type Point . 不, Body具有Point类型的位置属性。 So Body probably should not extend Point . 所以Body可能不应该扩展Point If you get rid of inheritance (of implementation) then you get rid of a lot of problems. 如果你摆脱继承(实现),那么你摆脱了很多问题。 That and use private (not protected !) and final liberally. 那和使用private (不受protected !)和final自由。

I quickly realized that doing this will create two variables inside the Body class called x and two other variables in Body called y. 我很快意识到这样做会在Body类中创建两个名为x的变量,在Body中创建另外两个名为y的变量。 How is this even possible, and why on earth does Java even allow it? 这怎么可能,以及为什么Java甚至允许它呢?

Actually no, you are not creating two variables with the same name, obviously a compiler should not and would not allow this. 实际上不,你没有创建两个具有相同名称的变量,显然编译器不应该也不允许这样做。

What you are doing is shadowing the existing variables defined as x and y , meaning that Body.x and Body.y are essentially overlapping the names for Point.x and Point.y, making the latter two variable completely inaccessible from the Body class ( link to Java Language Specification definition of "shadowing" ). 正在做的是遮蔽定义为xy的现有变量,这意味着Body.x和Body.y基本上与Point.x和Point.y的名称重叠,使得后两个变量完全无法从Body类中访问( 链接到Java语言规范定义的“阴影” )。

Name shadowing is generally perceiving as a bad practice and a cause of bugs, and if you turn up the javac compiler warnings, the compiler will dutifully warn you about this. 名称阴影通常被认为是一种不良做法和错误原因,如果你打开javac编译器警告,编译器将尽职尽责地警告你。

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

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