0

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

这是一个令我困惑的问题的简化示例。有三个类,一个父子类型和两个子子类型。这些类有一个 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 中的类继承的理解是正确的。

谢谢。

4

2 回答 2

1

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

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

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

然后在子类中调用它:

public ThinChild(Foo someFoo) {
    super(someFoo);
}
于 2012-05-26T22:18:43.650 回答
1

myFoo 在直接子类中可见,您只需使用“super.myFoo”对其进行限定。不过,这只适用于链上一级。因此,如果 ThinChild 也有一个带有 myFoo 的子类 ThinnerChild,则您无法访问位于 Parent 类中的“myFoo”实例。这个想法是你应该能够覆盖你自己对父母的行为,但你不应该能够覆盖你的父母(因此为什么不允许像 super.super 这样的东西)。

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

于 2012-05-27T05:35:26.753 回答