在 Java 中扩展另一个类的类中有 2 个同名变量
Posted
技术标签:
【中文标题】在 Java 中扩展另一个类的类中有 2 个同名变量【英文标题】:Having 2 variables with the same name in a class that extends another class in Java 【发布时间】:2010-10-20 20:03:09 【问题描述】:以下是我的项目代码的一部分:
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;
感谢您的宝贵时间
【问题讨论】:
所以如果我有一个带有 Point 参数的方法,并且我发送了一个 Body 类的实例,我将能够从该实例的 Point 访问 x 和 y 变量?如果输入参数的类型是 Body 而不是 Point,我将只能从 Body 访问 x 和 y 变量? 【参考方案1】:从某种意义上说,您正在覆盖超类的字段。但是由于没有字段重载(您只有一个给定名称的变量,类型无关紧要),因此意外地做起来要容易得多。这被称为变量“隐藏”或“阴影”。所以,你是对的,你最终会得到两个同名的字段。
你的第二个例子是正确的。它们是从超类继承的,并且由于它们没有被声明为私有的,因此它们对子类是可见的。直接引用超类的字段通常是不好的做法,除非有充分的理由,否则它们应该声明为私有的。您调用超级构造函数的示例是最好的方法。
另外,如果你隐藏了另一个同名的字段,你仍然可以将它们称为 super.x、super.y、vs.this.x、this.y,如果有的话,你应该避免这种情况可能的。
【讨论】:
所以如果我有一个带有 Point 参数的方法,并且我发送了一个 Body 类的实例,我将能够从该实例的 Point 访问 x 和 y 变量?如果输入参数的类型是 Body 而不是 Point,我将只能从 Body 访问 x 和 y 变量? @Martin Andersson 是的,因为 Point 只“知道”x 任何 y,而您的参数类型决定了您的代码如何“看到”对象。你当然可以低调点 p;身体 b = ((身体) p); b.质量 = xxx;但永远不要这样做! ;-)【参考方案2】:是的,您将有两个变量,一个隐藏另一个。允许它有两个原因:
-
假设您有一个基类
Base
和一个派生类Derived
,Base
的作者对此一无所知。 Base
的作者是否应该永远无法添加任何字段,仅仅因为派生类可能共享这些字段?或者当Base
的更改实际上不影响正确性时,Derived
是否应该停止编译?
您的字段几乎应该始终是私有的,此时名称是否重复并不重要——“一方”都不会知道另一方的变量。
【讨论】:
1.在我的初学者看来,当“派生”停止编译时很清楚,因为“基础”已经使用相同的标识符,但我认为有更深刻的理由允许这样做,谁知道......【参考方案3】:除其他人所说的:Body
是 Point
吗?不,Body
具有 Point
类型的位置属性。所以Body
可能不应该扩展Point
。如果你摆脱了继承(实现),那么你就摆脱了很多问题。那并随意使用private
(不是protected
!)和final
。
【讨论】:
虽然一般来说“优先组合胜过继承”是好的,但设计师也可能希望 Body 具有 Point 的所有属性(为了清楚起见,可能还有其他属性被省略了)。跨度> 【参考方案4】:我很快意识到这样做会在 Body 类中创建两个名为 x 的变量,并在 Body 中创建另外两个名为 y 的变量。这怎么可能,为什么 Java 甚至允许它?
实际上不,您并没有创建两个具有相同名称的变量,显然编译器不应该也不会允许这样做。
您在所做的是隐藏定义为x
和y
的现有变量,这意味着Body.x 和Body.y 本质上与Point.x 和Point 的名称重叠。 y,使后两个变量完全无法从 Body 类 (link to Java Language Specification definition of "shadowing") 中访问。
名称隐藏通常被认为是一种不好的做法和错误的原因,如果您打开 javac 编译器警告,编译器会尽职尽责地警告您。
【讨论】:
其实你仍然可以通过在 Body 类中使用 Point.this.x 和 Point.this.y 来访问这些变量 两个变量同名。它们只是在不同的类中声明。变量的名称只是“x”和“y”,而不是“Body.x”、“Body.y”、“Point.x”和“Point.y”。甚至您提供的有关遮蔽的链接也说:“某些声明可能会在其范围内被另一个同名声明所遮蔽 [...]” - 请注意“同名”部分。 J.S.:我认为 M.B.旨在描述性而非可执行代码。 换句话说,我知道它们不是静态的,我只是试图区分 Point 类的“x”和 Body 类的“x”。 我正在解决变量名称不同的说法。他们确实如此,这正是为什么一个人会影响另一个人。以上是关于在 Java 中扩展另一个类的类中有 2 个同名变量的主要内容,如果未能解决你的问题,请参考以下文章