2010-11-10 42 views
7

我有一个包含对定义对象的引用的对象实例系统。我为每个继承树都有一个顶级类。实例对象具有对相应定义类的通用引用。为什么不能识别它的超类边界(Java)?

在getter中使用泛型,顶级对象的子类可以在不投射的情况下获得正确类型的定义。然而,一个抽象类,再次子类不能:

class Def { } 

abstract class Animal<D extends Def> { 
    D def; 
    D getDef() { return def; } 
} 

class CatDef extends Def { } 
class Cat extends Animal<CatDef> { } 

abstract class BearDef extends Def { } 
abstract class Bear<D extends BearDef> extends Animal<D> { } 

class BlackBearDef extends BearDef { } 
class BlackBear extends Bear<BlackBearDef> { } 

class AnimalDefTest { 
    public static void main (String... args) { 
     Cat cat = new Cat(); 
     CatDef catDef = cat.getDef(); // CatDef works fine 

     Bear bear = new BlackBear(); 
     BearDef bearDef = bear.getDef(); // Error: Expected Def not BearDef? Why??? 
     BearDef bearDef2 = ((Animal<BearDef>)bear).getDef(); // Works 
    } 
} 

为什么getDef需要Bear强制转换为(Animal<BearDef>)得到一个BearDef?熊最终定义为extends Animal<? extends BearDef>

[编辑]更奇怪的是,如果我改变了熊类线:

abstract class Bear<D extends BearDef> extends Animal<BearDef> { } 

(在这种情况下,d是未使用的,是不相关的),它仍然不起作用。删除d及以下线路解决了上面的代码中的错误(但不会帮我做什么,我需要与子类的定义做):

abstract class Bear extends Animal<BearDef> { } 

回答

11

您使用的是原始类型Bear事实上,当应使用BearDef类型进行参数化。如果你写

Bear<BlackBearDef> bear = new BlackBear(); 

Bear<?> bear = new BlackBear(); 

它会正常工作。

另一件事:我不知道你打算如何使用这一点,但它似乎有可能我说,你会被罚款只是在做这个:

abstract class Bear extends Animal<BearDef> {} 

class BlackBear extends Bear { 
    // make use of covariant return type to make BlackBear return correct def 
    @Override 
    BlackBearDef getDef() { ... } 
} 

我的思考这个原因是如果您想要BeargetDef()方法返回BlackBearDef,该Bear参考需要参数化为Bear<BlackBearDef>。在这种情况下(无论如何),您实际上知道它是来自声明类型的BlackBear,所以您可能只是将其称为BlackBear。也就是说,这显然不总是那么简单,你的实际情况可能不会允许这样做。

+2

+1:打我给它。 – Powerlord 2010-11-10 16:58:32

+0

也是我+1。 – 2010-11-10 17:01:18

+0

* *有点合理,但是因为它知道它至少是一个BearDef,它不应该假设你在第二行有什么? – Nicole 2010-11-10 17:01:50

3

这将工作太:

Bear<?> bear = new BlackBear(); 
相关问题