隐藏类的实例变量

2022-09-03 04:54:08

我想知道为什么Java对一个超类和一个具有相同名称的实例变量的子类有这种奇怪的行为。

假设我们有以下类定义:

class Parent {
    int var = 1;
}

class Child extends Parent {
    int var = 2;
}

通过这样做,我们应该隐藏超类的变量 。如果我们没有明确指定通过调用访问的方式,那么我们就永远不能从子的实例访问。varParentvarsupervar

但是当我们有一个演员表时,这种隐藏机制会破坏:

Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.var); // prints out 1, instead of 2

这难道不是完全规避了现场隐藏的整个要点吗?如果是这样的话,那么这难道不会使这个想法完全无用吗?

编辑:我特别指的是Java教程中的这篇文章。它提到

在子类中,超类中的字段不能通过其简单名称引用。相反,该字段必须通过超级...

从我在那里读到的内容来看,这似乎暗示Java的开发人员在这样做时有某种技术。虽然我同意这是一个相当晦涩的概念,并且总体上可能是不好的做法。


答案 1

在 Java 中,数据成员不是多态的。这意味着 和 是两个不同的变量,碰巧具有相同的名称。在任何意义上,您都没有在派生类中“重写”;正如您自己发现的那样,这两个变量都可以彼此独立地访问。Parent.varChild.varvar

最好的前进方式实际上取决于你想要实现的目标:

  1. 如果不应该对 visible visible ,请将其 。Parent.varChildprivate
  2. 如果 和 是两个逻辑上不同的变量,请为它们指定不同的名称以避免混淆。Parent.varChild.var
  3. 如果 和 在逻辑上是相同的变量,则为它们使用一个数据成员。Parent.varChild.var

答案 2

字段隐藏的“点”仅仅是指定代码的行为,该代码确实为变量提供了与其超类中变量相同的名称。

这并不意味着被用作真正隐藏信息的技术。这是通过使变量私有来完成的...我强烈建议在几乎所有情况下都使用私有变量。字段是一个实现细节,应该对所有其他代码隐藏。