在Java中,为什么在父类和子类中声明的变量在子类的实例中是不可见的?

时间:2012-05-26 21:52:55

标签: java inheritance

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

这是一个令我困惑的问题的简化示例。有三个类,父类和两个子类。这些类有一个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中,断言失败了。这不是我所期望的。

此外,如果我将getFoo类中相同的Parent方法添加到我的ThinChild类中,则断言现在可以正常工作。这解决了我的直接问题但对我来说似乎不受欢迎,因为我现在在每个子类中维护相同的代码,我更愿意将它保存在父类中。

我的实际案例有点复杂,但我希望我已经掌握了所有相关细节。假设我有,是否有任何解释为什么这将是预期的行为?

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

感谢。

2 个答案:

答案 0 :(得分:1)

删除public Foo myFoo。在嵌套类中,此字段从父类扩展。您无法更改它,因为您有2个具有相同名称的变量。因此JVM使用较小的范围初始化变量。

另一个好方法是在父级中创建构造函数:

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

然后在子类中调用它:

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

答案 1 :(得分:1)

myFoo在直接子类中是可见的,您只需要使用“super.myFoo”来限定它。这只能在链条上升1级。因此,如果ThinChild也有一个带有myFoo的子类ThinnerChild,那么你就无法获得生活在Parent类中的“myFoo”实例。这个想法是你应该能够用你的父母覆盖你自己的行为,但你不应该覆盖你的父母(因此不允许像super.super这样的东西)。

话虽如此,删除子类上的实例很可能是你想要的,因为每个ThinChild和ThickChild实际上有两个“myFoo”实例,一个属于它,一个属于它的父级。