2017-08-17 144 views
2

我有几个类是Animal的子类,它本身是Lifeform的子类。所有这些类都有一个永远是自己类型的孩子,因此是通用的。下面简化代码:泛型的类引用自己作为Java中泛型的类型

public class Animal<T extends Animal> extends Lifeform { 
    T child; 

    private void initiate() { 
     setChild(Animal.class); 
    } 

    public void setChild(Class<T> animalType) { 
     T foundChild = findChild(animalType); 
     foundChild.setParent(this); 
     this.child = foundChild; 
    } 
} 

凡findChild是继承的方法:

public abstract class Lifeform { 
    private <L extends Lifeform> L findChild(Class<L> lifeformType) { 
     /* Do some stuff with lifeformType to find child */ 
     ... 
     return child; 
    } 
} 

需要注意的是大多数生命形式不会有一个孩子,即使用于识别孩子的方法是在生命形式类。

我得到一个编译错误,我尝试在Animal.initiate()中调用setChild(Animal.class)。

不兼容的类型:java.lang.Class中<动物>不能转换到的java.lang.Class < T>

Ť延伸动物,那么,为什么不能使用Animal.class作为这里有一个参数?

起初,我创建setChild不带任何参数,并试图做

findChild(T.class) 

但我意识到,我不能从一个普通的一样,获取类,并发现一个共同的解决办法是只添加类作为一个参数,这是我如何结束我现在拥有的。

我没有任何问题,如果我尝试在子类中使用setChild:

public class Bat extends Animal<Bat> { 
    private void fly() { 
     setChild(Bat.class); 
     child.fly(); 
    } 
} 

不幸的是,我确实需要一个动物的实例没有亚型少数情况下,因此我希望能够setChild with Animal作为类型。

我意识到我可以为Animal创建一个额外的子类,而是有一个包含setChild方法的抽象类AnimalAbstract。然而,这意味着我将不得不根据它们的使用方式来区分动物的方法。

有没有另一种方法来完成这项工作?

+0

如何你的'Lifeform'界面看起来像? –

+0

@AdamArold这是一个抽象类。我已经以简化形式添加了它。 – EJS

回答

1

在我看来,要解决这个问题的方法之一是参考保持在班上的孩子:

public class Animal<T extends Animal> extends Lifeform { 
    protected final Class<T> childClass; 
    T child; 

    public Animal(Class<T> childClass) { 
     this.childClass = childClass; 
    } 

    protected void initiate() { 
     setChild(childClass); 
    } 

    public void setChild(Class<T> animalType) { 
     T foundChild = findChild(animalType); 
     foundChild.setParent(this); 
     this.child = foundChild; 
    } 
} 

蝙蝠类将随即成为:

public class Bat extends Animal<Bat> { 
    public Bat() { 
     super(Bat.class); 
    } 

    private void fly() { 
     setChild(Bat.class); // or initiate(); 
     child.fly(); 
    } 
}