隐藏类的实例variables

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

假设我们有以下的类定义:

class Parent { int var = 1; } class Child extends Parent { int var = 2; } 

通过这样做,我们应该隐藏超类的variablesvar 。 如果我们没有明确地指定一种通过super调用来访问Parentvar的方法,那么我们永远不能从一个子实例访问var

但是当我们有演员的时候,这个隐藏机制就打破了:

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

这是不是完全规避了整个隐藏点? 如果是这样的话,那么这个想法是不是完全没用?

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

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

从我读到的那里,似乎暗示着Java的开发人员在做这件事的时候有了一些技巧。 虽然我同意这是一个相当晦涩的概念,一般来说可能是不好的做法。

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

最好的前进方向实际上取决于你想要达到的目标:

  1. 如果Parent.varChild不可见,则将其设为private
  2. 如果Parent.varChild.var是两个逻辑上不同的variables,给他们不同的名字,以避免混淆。
  3. 如果Parent.varChild.var在逻辑上是相同的variables,那么为它们使用一个数据成员。

字段隐藏的“点”仅仅是指定代码的行为,该代码的行为给予与其超类中的variables同名的variables。

这并不意味着被用作真正隐藏信息的技术 。 这是通过使variables私人开始…我强烈build议在几乎所有情况下使用私有variables。 字段是应该从其他所有代码隐藏的实现细节。

在Java中属性不是多态的,无论如何,声明一个公共属性并不总是一个好主意。 对于你正在寻找的行为,最好使用私有属性和访问器方法,如下所示:

 class Parent { private int var = 1; public int getVar() { return var; } public void setVar(int var) { this.var = var; } } class Child extends Parent { private int var = 2; public int getVar() { return var; } public void setVar(int var) { this.var = var; } } 

而现在,在testing时,我们得到了预期的结果,2:

  Child child = new Child(); Parent parent = (Parent)child; System.out.println(parent.getVar()); 

当你投射时,你可以有效地告诉编译器“我知道得更好” – 它暂停了正常的强types推理规则,并给你一个怀疑的好处。

通过说Parent parent = (Parent)child; 你告诉编译器“把这个对象看作是父对象的一个​​实例”。

另一方面,你把OO(good!)的“信息隐藏”原理与一个隐藏的副作用(通常是坏的)混为一谈。

正如你所指出的那样:

我们应该隐藏超类的variablesvar

这里的主要观点是variables不会像方法那样覆盖 ,所以当你直接调用Child.var时,你直接从Child类调用一个variables,当你调用Parent.var时,你从Parent类调用一个variables,如果他们具有相同的名字,则是重要的。

作为一个方面说明,我会说这是非常混乱,不应该被允许作为有效的语法。