【问题标题】:Java typecast with covariant return type具有协变返回类型的 Java 类型转换
【发布时间】:2017-05-09 14:06:16
【问题描述】:

我创建了一个带有协变返回类型的继承的小例子。基本上有三个不同的类:

主应用程序:

public class MainApp {
  public static void main(String[] args) {
  BaseManager manager = new BirdManager();
  BirdManager birds = (BirdManager) manager.getManager(); // <-- Why type cast here
  // prints BirdManager
  }
}

基地经理:

public abstract class BaseManager {
  private Map<ManagerType, BaseManager> list = new EnumMap<>(ManagerType.class);
  protected Map<ManagerType, BaseManager> getList() {
    return list;
  }
  public abstract BaseManager getManager();
}

鸟经理:

public class BirdManager extends BaseManager {
  public BirdManager getManager() {
    if (!super.getList().containsKey(ManagerType.BIRD)) {
        super.getList().put(ManagerType.BIRD, this);
    }
    return (BirdManager) super.getList().get(ManagerType.BIRD);
}

当我重写方法getManager() 以返回BirdManager 时,为什么我需要将BaseManager 类型转换为BirdManager

我使用了Can overridden methods differ in return type? 作为参考。

编辑:

我有不同的子模型,它们都继承自 BaseManager。所有模型都允许存在一次。我没有为每个模型使用单例,而是尝试将这些模型添加到列表中。使用getManager(),我想获得实际模型。也许我必须过度考虑我的设计。

【问题讨论】:

  • 那是因为manager 的类型是BaseManager,所以编译器只“知道”manager.getManager() 返回一个BaseManagerBaseManager.getManager() 的签名证实了这一点。 See this post。为什么还需要getManager() 方法?

标签: java inheritance


【解决方案1】:

您调用方法的manager 对象是BaseManager,而不是BirdManager。编译器不知道你实际上是在调用BirdManager 的方法,它只会在运行时知道,这就是你需要强制转换的原因。

【讨论】:

  • 好的,有道理。有没有办法避免使用某种模式或泛型进行类型转换?还是在这种情况下进行类型转换“足够好”?
  • 我真的不明白getManager() 方法的意义,但在BaseManager 类中可能会有这样的东西:public &lt;T&gt; T getManager() { return (T) this; }。我不建议使用它,这只是一种可能性,它破坏了泛型的整个目的(编译时类型安全)。
【解决方案2】:

因为 manager 是 BaseManager 而不是 BirdManager 的一个实例。这样您就可以将它与鸟类实例一起使用,您需要对其进行类型转换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多