用 List<?> 成员定义抽象泛型类

Posted

技术标签:

【中文标题】用 List<?> 成员定义抽象泛型类【英文标题】:Defining abstract generic class with List<?> members 【发布时间】:2016-02-14 11:51:16 【问题描述】:

即使为此想出一个干净的标题也是一个挑战。

基本思想是定义两个超类:一个用于“子”项,其成员引用其“父”,另一个用于包含子对象的“父”列表。 child->parent 和 parent->child 的链接是对称的。每个父/子超类都有定义和实现附加功能的子类。总是有一个并行的子类,这样child&lt;A&gt;parent&lt;A&gt; 配对。也就是说,parent&lt;A&gt; 将仅包含 child&lt;A&gt; 引用,而 child&lt;A&gt; 将仅引用 parent&lt;A&gt; - 子类型之间没有“交叉”。

我该如何表示?我已经坚持了好几天了,我对多层嵌套泛型类型越有创意,它就越糟糕。这就是我想做的:

abstract class ChildBase<T extends ChildBase<T>> 
    ParentBase<T> parent;

abstract class ParentBase<T extends ChildBase<T>>  
    LinkedList<T> childList;

class ChildSub extends ChildBase<ChildSub> 
    // ... class specific stuff

class ParentSub extends ParentBase<ChildSub> 
    // ... class specific stuff

这是一团糟。我怀疑有一种更简单、直接的方法可以做到这一点,而且可能是完全不同的方向。

【问题讨论】:

我很想知道您为什么需要T 来扩展ChildBase?这些类中是否会有一些方法要求它们是ChildBase?获取节点的兄弟姐妹就是一个例子。如果没有,那么您可以显着简化结构。 正如@sprinter 所说,也许需要深入了解您的问题域才能提供更好的设计。考虑更详细地描述所描述的类的应用。 您是否尝试过寻找基于接口的解决方案而不是继承?就我个人而言,我发现如果你只是解耦类而不是更多地耦合它们,很多这些问题会更容易解决。 【参考方案1】:

你的意思是class ParentSub extends ParentBase&lt;ChildSub&gt;

如果您进行这一更改,则一切都会编译。

这是一团糟。我怀疑有一种更简单、直接的方法可以做到这一点,而且可能是完全不同的方向。

实际上,与我见过的其他一些使用泛型的方式相比,这并没有那么糟糕。没有完全不同的方法可以实现您所缺少的。

唯一的选择(我认为你应该认真考虑)是使 ChildBaseParentBase 非泛型,并在必要时使用强制转换。泛型被引入到语言中,以帮助程序员编写正确的、类型安全的程序。当您的类之间存在复杂或循环的关系时,弄清楚如何正确使用泛型变得如此困难和耗时,以至于根本没有使用它们的好处。

【讨论】:

是的,我已经尝试将特定类型的内容添加到子类中(而不是在类之外进行强制转换)。我看到的权衡是在维护中。当需要更改时,我需要更加努力地确保根据需要将它们传播到所有子类;确实,花在循环/嵌套通用方法工作上的时间是浪费的,并且可能导致脆弱的代码在我每次需要更改时都会中断。 @ags 模式MyClass&lt;T extends MyClass&lt;T&gt;&gt; 的一个问题(除了非常混乱之外)是它非常严格,因为它不能很好地与继承混合。 (***.com/questions/33632871/…)。如果您将来决定扩展ChildSub,您将面临更严重的问题,因为您已经将类型参数固定为ChildSub【参考方案2】:

我花了一点时间来分析你有什么,我真的不明白有什么问题。你的定义似乎工作得很好。这到底是怎么一团糟?

将您拥有的内容扩展到更具体的内容,例如:

abstract class Child<T extends Child<T>> 

    private final Parent<T> parent;


    protected Child(Parent<T> parent) 
        this.parent = parent;
    

    Parent<T> getParent() 
        return this.parent;
    


abstract class Parent<T extends Child> 

    private final LinkedList<T> children = new LinkedList<>();

    void addChild(T child) 
        this.children.add(child);
    

    List<? extends T> getChildren() 
        return Collections.unmodifiableList(this.children);
    

我可以很容易地表达你说你想要表达的想法:

class Daedalus extends Parent<Icarus>  

class Icarus extends Child<Icarus> 

    public Icarus(Parent<Icarus> parent) 
        super(parent);
    


然后做

Daedalus parent = new Daedalus();
Icarus child = new Icarus(parent);
parent.addChild(child);
for(Icarus aChild : parent.getChildren()) 
    //do something with aChild

我一点也不觉得这很乱,从你的问题中我也不清楚为什么这会是一个问题。

【讨论】:

以上是关于用 List<?> 成员定义抽象泛型类的主要内容,如果未能解决你的问题,请参考以下文章

泛型类的基本使用

JAVASE(十五) 泛型 :泛型用例自定义泛型类通配符

自定义泛型结构:泛型类泛型接口泛型方法

java中啥是泛型,怎么用泛型?

从非泛型类调用抽象泛型类中定义的方法的最佳方法是啥

C#泛型类,泛型接口,泛型方法,泛型委托怎么用