2017-08-17 148 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(); 
    } 
}