【问题标题】:question about hiding/shadowing member-variables in Java关于在 Java 中隐藏/隐藏成员变量的问题
【发布时间】:2011-09-22 08:15:39
【问题描述】:

我想了解 Java 中隐藏的工作原理。 所以让我们假设你有以下代码

public class A{
    protected SomeClass member;
    public A(SomeClass member){
        this.member = member;
    }
}  

public class B extends A{
    protected SomeClass member;
    public B(SomeClass member){
        super(member);
    }
    public static void main(String[] args){
        SomeClass sc = new SomeClass();
        B b = new B(sc);
        System.out.println(b.member.toString());
    }
}

如果我编译我会得到 NullPointerException。我认为这将是 sc.toString(); 的输出;

我把这段代码改成

public class A{
    protected SomeClass member;
    public A(SomeClass member){
        setMember(member);
    }
    public void setMember(SomeClass sc){
       this.member = sc;
    }

}  

public class B extends A{
    protected SomeClass member;
    public B(SomeClass member){
        super(member);
    }
    public void setMember(SomeClass sc){
       this.member = sc;
    }
    //...main
}

它得到了预期的输出...... 好的 setMember of B 覆盖 A 中的那个,所以我可以用这种方式解释这一点。 我玩了一下并从 B 中删除了 setMember 以取回我的 NullPointerException。但是如果我将 A 的代码更改为

,它会再次编译并给我输出
public class A{
    protected SomeClass member;
    public A(SomeClass member){
        setMember(member);
    }
    public void setMember(SomeClass sc){
       member = sc;
    }

} 

在我看来,SomeClass 成员实际上有两个实例......但是如果有两个实例,那么阴影意味着什么?隐藏只对第二种情况有用吗?

【问题讨论】:

  • 您的第一个示例无法编译,因为b 没有成员sc。它在System.out.println(b.sc.toString()); 失败。如果你的编译器接受这个,它就坏了。

标签: java shadowing member-hiding


【解决方案1】:

我假设您的意思是第一个代码示例的最后一行是 b.member.toString()

有两个名为“member”的成员变量,在您的两个示例中,只有一个被设置,因为只有一个对 this.member 的赋值被调用。要修复第一个示例,您通常会说

public B(SomeClass member) {         
    super(member);
    this.member = member;
} 

但我认为您已经理解了这一点,并且真的在问为什么这种语言是这样设计的。它与超类实现的封装有关。超类的作者应该能够在不破坏子类的情况下重写它,反之亦然。想象一下,如果 B.member 排在第一位是因为 B 的作者虽然“成员”是个好东西,但后来 A 的作者也有同样的想法。

但是,该系统并不完美,您的第二个示例说明了原因。如果先出现B.setMember(),然后A 的更高版本引入A.setMember(),那么A 的作者可能无法预期覆盖B.setMember() 方法,并按照您显示的方式编写构造函数,结果A.member永远不会被初始化。 C# 引入了“overrides”关键字来捕捉这类事情,Java 将其借用为“@overrides”,但该注解在 Java 中不是强制性的,因此效果不佳。

【讨论】:

  • 是的,我的意思是我的 main 方法中的 member.toString() - 这只是一个错字;)但无论如何这个答案很有帮助
猜你喜欢
  • 1970-01-01
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多