【问题标题】:How to return an actual instance from a method with a generic return type如何从具有通用返回类型的方法返回实际实例
【发布时间】:2013-05-11 18:26:57
【问题描述】:

我很难创建类型安全的行为,我将使用一个通用示例来强调我的问题:

我有一个接口BoxCreator,它的定义是:

public interface BoxCreator{
    public Box create(int id ,List<Box> others);
}

还有一个通用的Box 类(一个Box 可以包含其他几个Boxes),它具有int getId()Box getInternalBox(int id) 等方法。

假设我有一个 Shed implements BoxCreator,Container 类(其中容器只是一个通用接口,带有 add 和 remove 之类的操作)。我可以把新东西放在棚子里,它会把它们装在一个实现BoxShedBox中。

到目前为止一切都很好,当我尝试制作一些其他的类来做一些不同的事情时,问题就出现了,例如CoolShed extends Shed implements BoxCreator,它将把事情放入CoolBoxes(扩展ShedBox)。

目前它可以工作,但我在CoolShed 类中有几个向下转换(从一般的BoxCoolBox)可能“不漂亮”。

我正在寻找的是一种制作方法

Shed&lt;T extends ShedBox&gt; implements BoxCreator&lt;T&gt;

然后在实现CoolShed 时,我会做类似的事情

CoolShed extends Shed&lt;CoolBox&gt; implemets BoxCreator&lt;CoolBox&gt;

我试图使各种类通用,但无法创建通用create 方法,因为我无法实例化T 或为此返回一个。所以我有点失落。

几个注意事项:

  1. CoolShed 使用了很多 Shed 逻辑,但我只想让它使用 CoolBox 类作为容器。
  2. 目前Shed 有一个BoxCreator 的实例,因此在创建CoolShed 时,我只需将CoolShed 设为新创建者即可。
  3. CoolShed 将只有 CoolBox 实例,但我真的不介意在 Shed 类中扩展 ShedBox

我只是找不到一个很好的解释来说明如何实现所需的行为,也无法判断我现有的演员表是否正常。

我知道我的示例很长,我很乐意尽我所能使其更清楚。

编辑

让问题更清晰的代码模板:

public interface BoxCreator{
    public Box create(int id ,List<Box> others);
}

public interface Box{
    void put()
    void addAnother(Box box);
}

public class ShedBox implements Box{
    void put()
    void addAnother(Box box);
}

public class CoolBox extends ShedBox{ //has some extra features but moslty the same
    void put()
    void addAnother(Box box);
}

public interface Container {
    Box addValue(int value);
    Box getBox(int id);
    .
    .
}

public class Shed implements Container, BoxCreator {
    BoxCreator creator;
    SomeCollection<Box> boxes;
    Shed(){
        creator = this;
        .
        .
        .
    }

    Box addValue(int id){
        .
        .//some logic to get otherBox here
        .
        Box box = creator.createBox(id,otherBox);
    }

    Box getBox(int id);

    public Box create(int id ,Box other){
        return new ShedBox(id,others)
    }
}

public class CoolShed extends Shed implements BoxCreator {

    CoolShed(){
        creator = this;
        .
        .
        .
    }

    addValue(int id){
        Box boxAdded = super.add(id)
        .
        .
        .
        CoolBox box = (CoolBox)boxAdded; // The questionable cast
        .
        . //Some logic that involves CoolBox specific actions 
        .
    }

    public Box create(int id ,Box other){
        return new CoolBox(id,others)
    }

}

【问题讨论】:

  • 最好包含一个包含各种类的代码示例以显示您要实现的目标...
  • CoolShed 可以只包含 CoolBox 还是可以包含任何 Box?
  • @owlstead 有很多(相信我 :) )代码,其中大部分与问题无关,所以我担心它只会让人们更加困惑,但我做了一些可以更好地解释问题的通用模板。
  • @LeeMeador 感谢您指出这一点,CoolShed 将只有 CoolBox 实例,但我不介意在 Shed 类中扩展 ShedBox 的任何内容。我已将此信息添加到问题中。

标签: java generics types return


【解决方案1】:

(之前的答案已删除)

编辑:这个解决方案应该更好,假设 others 可能包含任何框:

public interface BoxCreator {
    public Box create(int id, List<Box> others);
}
public class Shed implements BoxCreator {
    @Override
    public ShedBox create(int id, List<Box> others) {
        ...
    }
}
public class CoolShed extends Shed {
    @Override
    public CoolBox create(int id, List<Box> others) {
        ...
    }
}

另外,不要这样做:

BoxCreator creator;
creator = this;
creator.create(...);

相反,您应该写成this.create(...) 或干脆写成create(...)。然后您不必从 Box 转换为所需的子类,因为从 create 返回的值已经是 ShedBoxCoolBox 类型。

【讨论】:

  • 我实际上已经尝试过该选项,但我无法从create 返回new ShedBox(),也许我的更新可以让我的情况更清楚。
  • @owlstead 我考虑使用B,因为它们都是Box 的实例,但决定只使用T
  • @Lonenebula 谢谢,但是当使用public Box create(...) 作为实现签名时,它会发出警告“未经检查的覆盖:返回类型需要未经检查的转换”,并且用法会发出“未经检查的调用以创建为原始类型BoxCreator”警告。使用public T create(...) 不会编译..
  • 我有点困惑,如果 add 返回 Box 我仍然必须将其转换为 CoolBox... 顺便说一句,为什么使用 creator 被认为不好?
  • @SadStudent creator 的类型为BoxCreator,而this 的类型为ShedCoolShed,因此使用creator 会丢失有关方法和字段的信息。例如,在我的编辑中BoxCreator.create 返回一个Box,但Shed.create 返回一个ShedBox
猜你喜欢
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多