【问题标题】:Java Method return Types from InheritanceJava 方法从继承返回类型
【发布时间】:2017-03-26 23:21:50
【问题描述】:

我正在类Parent 中编写一个方法,它返回一组对象A。但是,我有一个类Child(继承形式Parent)。我希望它返回一组对象BB 继承自A)。

更具体地说,我的方法看起来像这样(它现在会引发编译错误)。

Parent类方法:

public abstract <T extends A> Set<T> getSet();

Child 类(扩展Parent 类)方法:

public <T extends B> Set<T> getSet() {...}

这样做有可能吗,还是没有意义?

【问题讨论】:

  • 类型参数有范围。我认为您应该将 ParentChild 类都定义为内部类。然后你可以使用类级别的类型参数来得到你想要的
  • @Jude 你能解释一下将 both 定义为内部类的意思吗?
  • 我对你的帖子做了一些格式化。请注意,在降价中,您通过留下一个空行来创建一个新部分。你不必这样做&lt;br/&gt;

标签: java oop generics inheritance


【解决方案1】:

首先,让我解释一下为什么您的代码无法编译。基本上,如果您有class A {}class B extends A {},那么Set&lt;B&gt; 不是Set&lt;A&gt; 的子类型。所以如果你的父方法返回一个Set&lt;A&gt;,你的覆盖必须返回同样的东西。 Set&lt;B&gt; 是一个完全不同的类型

同样,Set&lt;T extends B&gt; 不是Set&lt;T extends A&gt; 的子类型。完整解释见Java docs

我能想到的最接近的解决方案是使用通配符:

class A {}

class B extends A {}

abstract class Parent {
    abstract Set<? extends A> getSet();
}

class Child extends Parent {
    Set<? extends B> getSet() {
        return new HashSet<B>();
    }
}

Set&lt;? extends B&gt; Set&lt;? extends A&gt; 的子类型,现在由于covariant return types 而起作用(欣赏下面 Lii 和 Marco13 的 cmets)。

根据您要达到的具体目标,这可能比您预期的要有限,但可能已经接近了。

正如 Jude 所说,也许使用内部类也可以实现类似的效果,但我不认为这会是一个更方便的解决方案。

【讨论】:

  • 这似乎是解决问题的好方法,你说得对,通配符是这里的关键。但是该解决方案包含一些不必要的元素:1)您可以完全删除类上的类型参数。你实际上根本不使用它们。 2) Child.getSet 可以声明为返回Set&lt;B&gt;,通配符只在超类上是必需的(除非您打算创建另一个扩展Child 的类并再次覆盖该方法。)
  • 我实际上确实使用了类型参数 - 我返回了一个 T 类型的新 HashSet。是的,我可以删除类型参数(这是我最初的解决方案),但是 Set 的实际类型将具有由方法确定。 IE。即使返回类型相同,您也需要 Set、Set 等的新方法。我的解决方案允许通过创建同一类的新实例来实现此行为,而只是使用不同的类型参数。如果我误解了你的意思,请原谅我!
  • 好的,那么我理解您对类上的类型参数的意图。但我不认为这是海报所要求的。而且我仍然对您使用T 感到困惑。仅给出您显示的代码,类型参数根本没有意义。您可以将new HashSet&lt;T&gt;() 更改为new HashSet&lt;B&gt;()(或new HashSet&lt;&gt;()),代码将以完全相同的方式编译和工作。也许您希望 getSet 改为返回 Set&lt;T&gt;Set&lt;? extends T&gt;
  • 同意,Parent 上肯定不需要输入参数(已经修改了我的答案)。你是对的,只给出这个代码,它是否在Child 上也没有什么区别,因为你不能用通用参数做很多事情。您可以使用一些额外的代码,例如如果您提供了一种实例化 T 的方法。无论如何,也不完全确定 OP 试图实现什么,这就是为什么我不想首先给出答案... :]
  • 编辑后的代码无法编译,带有&lt;T extends B&gt; extends Parent &lt;B&gt; 部分。同样:&lt;T extends B&gt;&lt;B&gt; 可以简单地省略。关键是通配符,事实上Set&lt;? extends B&gt;确实Set&lt;? extends A&gt;的子类型,而B extends A(这正是Lii指出的协方差)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
  • 2014-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多