隐藏类的实例variables
我想知道为什么Java有一个超类和具有相同名称的实例variables的子类这种奇怪的行为。
假设我们有以下的类定义:
class Parent { int var = 1; } class Child extends Parent { int var = 2; }
通过这样做,我们应该隐藏超类的variablesvar
。 如果我们没有明确地指定一种通过super
调用来访问Parent
的var
的方法,那么我们永远不能从一个子实例访问var
。
但是当我们有演员的时候,这个隐藏机制就打破了:
Child child = new Child(); Parent parent = (Parent)child; System.out.println(parent.var); // prints out 1, instead of 2
这是不是完全规避了整个隐藏点? 如果是这样的话,那么这个想法是不是完全没用?
编辑 :我特指Java教程中的这篇文章 。 它提到
在子类中,超类中的字段不能被其简单名称引用。 相反,该字段必须通过超级访问…
从我读到的那里,似乎暗示着Java的开发人员在做这件事的时候有了一些技巧。 虽然我同意这是一个相当晦涩的概念,一般来说可能是不好的做法。
在Java中,数据成员不是多态的。 这意味着Parent.var
和Child.var
是两个具有相同名称的不同variables。 你在派生类中没有任何意义上的“重写” var
; 正如你自己发现的那样,两个variables都可以独立访问。
最好的前进方向实际上取决于你想要达到的目标:
- 如果
Parent.var
对Child
不可见,则将其设为private
。 - 如果
Parent.var
和Child.var
是两个逻辑上不同的variables,给他们不同的名字,以避免混淆。 - 如果
Parent.var
和Child.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,如果他们具有相同的名字,则是重要的。
作为一个方面说明,我会说这是非常混乱,不应该被允许作为有效的语法。