考虑int a
这些类中的变量:
class Foo {
public int a = 3;
public void addFive() { a += 5; System.out.print("f "); }
}
class Bar extends Foo {
public int a = 8;
public void addFive() { this.a += 5; System.out.print("b " ); }
}
public class test {
public static void main(String [] args){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
我明白这个方法addFive()
已在子类中被重写,并且在类测试中,当引用子类的基类引用用于调用重写的方法时,子类版本addFive
叫做。
但是公共实例变量呢a
?当基类和派生类具有相同的变量时会发生什么?
上述程序的输出是
b 3
这是怎么发生的?
实际上有两个不同的公共实例变量,称为a
.
- Foo 对象有一个
Foo.a
多变的。
- Bar 对象同时具有
Foo.a
and Bar.a
变量。
当你运行这个时:
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
the addFive
方法正在更新Bar.a
变量,然后读取Foo.a
多变的。要阅读Bar.a
变量,你需要这样做:
System.out.println(((Bar) f).a);
这里发生的事情的技术术语是“隐藏”。请参阅 JLS第 8.3 节 http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.3, and 第8.3.3.2节 http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.3.3.2举个例子。
请注意,隐藏也适用于static
具有相同签名的方法。
但是,具有相同签名的实例方法是“重写”而不是“隐藏”,并且您无法从外部访问被重写的方法的版本。 (在重写方法的类中,可以使用以下方式调用重写的方法super
。然而,这是唯一允许这样做的情况。通常禁止访问重写方法的原因是它会破坏数据抽象。)
The 推荐方式为了避免(意外)隐藏的混乱,请将实例变量声明为private
并通过 getter 和 setter 方法访问它们。有很多other使用 getter 和 setter 也是有充分理由的。
还应该注意的是: 1)暴露公共变量(如a
)通常是一个坏主意,因为它会导致弱抽象、不必要的耦合和其他问题。 2) 故意宣布第二次公开a
子类中的变量确实是一个糟糕的主意。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)