2017-05-09 64 views
0

我已经为协变返回类型创建了一个继承的小例子。有basicly三个不同的类别:具有协变返回类型的Java类型转换

MainApp:

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

BaseManager:

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

BirdManager:

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); 
} 

为什么我需要强制转换BaseManagerBirdManager当我重写方法getManager()返回BirdManager

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

编辑:

我有不同的子型号,所有从BaseManager继承。所有型号都允许存在一次。我试图将这些模型添加到列表中,而不是为每个模型使用单例。随着getManager()我想获得实际的模型。也许我必须重新设计我的设计。

+1

这是因为'manager'属于'BaseManager'类型,所以编译器只'知道''manager.getManager()'返回一个'BaseManager'。 'BaseManager.getManager()'的签名证实了这一点。 [见这篇文章](http://stackoverflow.com/questions/16730109/difference-between-object-type-and-reference-type)。为什么你需要'getManager()'方法呢? –

回答

3

您打电话给您的方法的manager对象是BaseManager,而不是BirdManager。编译器不知道你实际调用了一个BirdManager的方法,它只会在运行时才知道,这就是为什么你需要一个强制转换。

+0

好的,这是有道理的。有没有办法避免使用某种模式或泛型的类型转换?或者在这种情况下强调“足够好”? – FaltFe

+0

我真的不明白'getManager()'方法的意义,但是'BaseManager'类中可能类似这样:'public T getManager(){return(T)this; }'。我不建议使用它,这只是一种可能性,它打破了泛型的全部目的(编译时类型安全性)。 – Shadov

0

因为manager是BaseManager的一个实例,而不是BirdManager。因此,您可以将它用于鸟类实例,您需要对它进行类型化。