【问题标题】:Java generics hierarchyJava 泛型层次结构
【发布时间】:2016-05-31 07:25:19
【问题描述】:

我正在尝试创建类的层次结构,从具有泛型类型的抽象类开始。然后在第二代子类中使用泛型的扩展类型。既然我很确定这还不清楚,这里有一个例子:

这个想法是有一个项目表,所以基本上:

abstract class AbstractTableOfItems<T> -> 表的泛型

class Foo -> 一种物品

class Bar -> 项目上的另一种类型

class SonOfFoo extends Foo

class TableOfFoo extends AbstractTableOfItems<Foo>

class TableOfBar extends AbstractTableOfItems<Bar>

到目前为止一切都很好,一切都很好(我们不要关心课程的内容,这不是重点)。

但是,我想要一个SonOfFoo 的表,并且我希望它扩展TableOfFoo,因为SonOfFoo 继承自Foo。这似乎是不可能的。可能我想错了,但我就是不明白为什么。

class TableOfSonOfFoo extends TableOfFoo

编译但错误,因为它仍然是Foo 的表,使用的泛型类型为Foo

class TableOfSonOfFoo extends TableOfFoo<SonOfFoo>

不会编译,因为泛型类型在 AbstractTableOfItems 上。

好吧,我说,让我们尝试重新定义TableOfFoo,以便它可以接受继承:

class TableOfFoo extends AbstractTableOfItems<? extends Foo>

又错了,“超类型不能指定任何通配符”(我不确定我是否完全理解这一点)。

我不能碰AbtractTableOfItems,因为它不会像我想要的那样通用。所以我有点卡在这里。 我知道只要让TableOfSonOfFoo 直接从AbstractTableOfItems 继承就可以工作,但是我会失去TableOfFoo 的所有实现。

我可以解决这个问题,但我正在尝试考虑层次结构,并理解为什么这不起作用。

【问题讨论】:

    标签: java generics inheritance


    【解决方案1】:

    这将编译:

    class TableOfFoo<F extends Foo> extends AbstractTableOfItems<F>
    

    也就是说:我不喜欢上面的设计。具有具体类型 TableOfFoo 和 TableOfBar 意味着这些类可能做的比它们应该做的更多。也许您想检查您的设计,看看是否可以通过使用聚合而不是继承来简化事情。

    【讨论】:

    • 我知道,但我正在为他的这部分问题提供替代方案class TableOfFoo extends AbstractTableOfItems&lt;? extends Foo&gt;。我认为整个问题都不容易回答。
    • 谢谢,这似乎有效。缺点是每次我使用“F”类型和 TableOfFoo 类时,我都必须将其显式转换为 Foo,而之前它是隐式的。但它实际上是这样工作的。 “也许你想检查你的设计,看看你是否可以通过使用聚合而不是继承来简化事情。”也许确实,我不太确定这种设计的相关性。
    • @Zazou 听起来不太对劲。正确使用泛型时,您不需要强制转换。也许您应该为此提出一个后续问题
    • 我仔细检查过,比这更微妙;它是一个在返回 T 对象的抽象类中定义的方法,而不是在 TableOfFoo 中重新实现。
    【解决方案2】:

    您可以将TableOfFoo 设为通用,例如

    class TableOfItems<T> extends AbstractTableOfItems<T>
    

    然后将您想要共享的所有功能拉入其中。然后创建它的子类:

    class TableOfFoo extends TableOfItems<Foo>
    class TableOfSonOfFoo extends TableOfItems<SonOfFoo>
    

    请记住,AbstractTableOfItems&lt;Foo&gt; 不是AbstractTableOfItems&lt;SonOfFoo&gt; 的超类型,因此TableOfFooTableOfSonOfFoo 实际上是层次结构中的兄弟。

    【讨论】:

    • 感谢您的回答,但通过这样做,TableOfItems 将是通用项目“T”的表,而不是 Foo 表,这意味着我不能使用 Foo 作为我的通用类型这个类的方法。这正是这种层次结构的重点。
    • @Zazou 所以给类型变量添加一个绑定:T extends Foo
    • 但这将是一个 TableOfFoo,并且不需要 TableOfItems,这将是 Sean Patrick Floyd 的答案,就在上面 ;)
    • 嗯,不一样。但如果他的回答对你有用,那就太好了。
    【解决方案3】:

    宁愿将其写入 cmets,但还没有足够的声誉。你试过了吗:

    class TableOfSonOfFoo extends AbstractTableOfItems<SonOfFoo>
    

    这对我来说似乎是合法的,并且会是我的第一个猜测。

    【讨论】:

    • 1) 请不要将问题写成答案。如果您对 cme​​ts 没有足够的声誉,请回答问题,直到您拥有为止。 2)OP明确解释说他不想直接扩展AbstractTableOfItems
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 2013-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多