当基类和派生类都具有同名变量时会发生什么

2024-05-06

考虑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(使用前将#替换为@)

当基类和派生类都具有同名变量时会发生什么 的相关文章

随机推荐