列表<a> referring to a List<subclass-of-a></subclass-of-a></a>

时间:2011-07-26 12:12:52

标签: java list arraylist subclass superclass

如果我有一个A类,其中包含A类儿童的列表,如

public Class A
{
    protected List<A> children = new ArrayList<A>();
    ...
}

那么在子类B中是否可以拥有另一个C类的子级并在A类中创建对子列表的引用? A类具有其他类想要使用的方法,例如送孩子去。但是,A类是一般类,B和C更具体。因此,为了使代码的读取更容易并避免大量的类型转换,我希望超类的List能够引用子类的List。

因此,当我更新 otherChildren 时,子级列表也会更新。我想在下面的示例中做一些事情,但是这样做不起作用,也不能用(children =(List&lt; A&gt;)otherChildren)进行投放。

但是无论如何要实现这个目标吗?我真的很想避免所有的类型转换。

public Class B extends A
{
    private List<C> otherChildren = new ArrayList<C>();

    public B()
    {
        children = otherChildren;
        ...
        // Modification of otherChildren will result in the same
        // modification in children
    }
}

public Class C extends A
{
     ...
}

3 个答案:

答案 0 :(得分:3)

你不能这样做,因为他们是不同的类型。您可以对List<A>的实例执行的操作之一是添加A的任意实例;你不能在List<C>上这样做,因为它是一种更受限制的类型。

修复方法是使A采用类型参数:

public class A <T extends A> {
    protected List<T> children = new ArrayList<T>();
    // ...
}

public class B extends A<C> {
    private List<C> otherChildren = new ArrayList<C>();
    public B() {
        children = otherChildren;
    }
    // ...
}

public class C extends A<? extends A> {
    // Or some such
}

当然,此时你也可以说你完全不需要otherChildren。您可以直接在子类中的children上操作,它仍然可以在没有显式强制转换的情况下工作。

答案 1 :(得分:2)

通过让孩子们引用其他孩子,你试图给A一个List<C>作为List<A>的视图,然后A可以合理地期望将A对象添加到它认为是列表的内容中As,但实际上应该是Cs的集合。

这在概念上无效。

如果此作业有效,则可能在C中,您的otherChildren应声明为List<A>。这引出了一个问题:为什么你不能直接使用children数组呢?

编辑:

我认为你需要一个更复杂的A,也许使用带有“extend”参数的泛型。所以A没有As的列表,但是没有As的列表。

答案 2 :(得分:2)

您所要做的就是将A类中的孩子声明更改为:

protected List<? extends A> children = new ArrayList<A>();