2012-05-26 51 views
0

具体来说,为什么在父类和子类中声明的变量在传递给参数为父类的方法的子类实例中不可见?在Java中,为什么在父类和子类中声明的变量在子类的实例中不可见?

这是一个令我困惑的问题的简单例子。有三个类,一个父类和两个子类。该班有一个Foo对象作为一个字段,这个静态类型的工厂方法:

class Parent { 
    public Foo myFoo; 

    public static ThinChild createThinChild(Foo someFoo) { 
     ThinChild thinChild = new ThinChild(someFoo); 
     return thinChild; 
    } 

    public Foo getFoo() { 
     return myFoo; 
    } 
} 

class ThinChild extends Parent { 
    public Foo myFoo; 

    public ThinChild(Foo someFoo) { 
     myFoo = someFoo; 
    } 
} 

class ThickChild extends Parent { 
    public Foo myFoo; 

    public ThickChild(Foo someFoo) { 
     myFoo = someFoo; 
    } 
} 

现在考虑这个处理程序类:

class ChildHandler { 
    private void doSomethingToThinChild(ThinChild thinChild) { 
     assert(thinChild.getFoo() != null); 
     doSomethingToAllChildren(thinChild); 
    } 

    private void doSomethingToAllChildren(Parent thinOrThickChild) { 
     assert(thinOrThickChild.getFoo() != null); 
    } 
} 

当我打电话doSomethingToThinChild,断言通过。但在方法doSomethingToAllChildren中,断言失败。这不是我所期望的。

此外,如果我在Parent类中为我的ThinChild类添加了相同的确切getFoo方法,则断言现在可用。这解决了我眼前的问题,但对我来说似乎不受欢迎,因为我现在在每个子类中保持相同的代码,我只是希望将其保留在父代中。

我的实际情况有点复杂,但我希望我已经记录了所有相关的细节。假设我有,是否有解释为什么这会是预期的行为?

有可能是我的实际代码中有一个额外的复杂因素,我没有在这里表示。但是我首先想确认我对Java中的类继承的理解是正确的。

谢谢。

+1

你是说'class ThinChild extends Parent'? – alaster

+0

您不需要在嵌套类中声明 'public Foo myFoo;'。 myFoo已经有 – alaster

+1

这三个类是完全不相关的。没有课程扩展任何其他课程。处理程序不会编译。 –

回答

1

删除public Foo myFoo。在嵌套类中,该字段从父类继承。你不能改变它,因为你有两个同名的变量。所以JVM初始化了范围较小的变量。

另外的好办法是在父母创建的构造函数:

public Parent(Foo someFoo) { 
    myFoo = someFoo; 
} 

然后调用它的子类:

public ThinChild(Foo someFoo) { 
    super(someFoo); 
} 
+0

删除子类中声明的字段解决了我的问题。谢谢。但我不明白为什么它很重要。你能否更新答案来强调这一点,并帮助我理解为什么它很重要,如果可能的话? – klenwell

+0

变量myFoo在嵌套类中不可见,因为您有两个具有相同名称的变量,所以无法更改它。所以JVM初始化变量的范围较小 – alaster

+0

谢谢@alaster。编辑你的答案,包括你的意见,并选择它。 – klenwell

1

myFoo是直接子类可见,你只需要限定它与“super.myFoo”。尽管这只能在连锁店上升1级。所以如果ThinChild的子类ThinnerChild也带有一个myFoo,那么您无法访问父类中的“myFoo”实例。这个想法是,你应该能够覆盖你的父母的行为,但你不应该能够覆盖你的父母(因此为什么像super.super是不允许的)。这就是说,删除子类上的实例很可能是你想要的,因为每个ThinChild和ThickChild在这种情况下有两个“myFoo”实例,一个属于它,另一个属于父级。

相关问题