2011-10-05 303 views
1

嘗試寫遺傳算法一些通用代碼的通用延伸和我有一個抽象類基因型如下:實例化的抽象類

public abstract class Genotype { 
private ArrayList<Gene> genotype = new ArrayList<Gene>(); 

//... 

public Genotype(ArrayList<Gene> genotype) { 
    setGenotype(genotype); 
    setGenotypeLength(genotype.size()); 
} 

public abstract Phenotype<Gene> getPhenotype(); 

public abstract void mutate(); 

//... 
} 

此類旨在被擴展和子類明顯提供了getPhenotype()和mutate()的實現。但是,我也有第二個類,它以兩個Genotype對象作爲參數,並返回一個包含Genotype對象的ArrayList。因爲我沒有在這一點知道的擴展基因型對象的類型,我需要如下使用泛型參數:

public class Reproducer { 

//... 

    private <G extends Genotype> ArrayList<Genotype> crossover(G parent1, G parent2) { 
     ArrayList<Genotype> children = new ArrayList<Genotype>(); 

     ArrayList<Gene> genotypeOne = ArrayListCloner.cloneArrayList(parent1.getGenotype()); 
     ArrayList<Gene> genotypeTwo = ArrayListCloner.cloneArrayList(parent2.getGenotype()); 

     //one point crossover 
     int p = gen.nextInt(genotypeOne.size()); 

     for (int i = 0; i < p; i++) { 
      genotypeOne.set(i, genotypeOne.get(i)); 
      genotypeTwo.set(i, genotypeTwo.get(i)); 
     } 
     for (int i = p; i < 10; i++) { 
      genotypeOne.set(i, genotypeTwo.get(i)); 
      genotypeTwo.set(i, genotypeOne.get(i)); 
     } 

     children.add(new G(genotypeOne)); //THROWS ERROR: Cannot instantiate the type G 
     children.add(new G(genotypeTwo)); //THROWS ERROR: Cannot instantiate the type G 

     return children; 
    } 
} 

然而,因爲我需要返回G型的兩個對象在一個ArrayList我清楚地有一個問題,我不能實例化新的Genotype對象,因爲它們是1.泛型類型,可能是2.抽象的。

這可能是一起討論事情的糟糕方式,但如果有人有一個很好的解決方案。謝謝。

回答

3

我會用一個工廠方法在Genotype

public abstract class Genotype { 
    public abstract GenoType newInstance(); 
} 
+0

謝謝,這不一定是一個靜態的方法嗎?顯然我不能有一個抽象的靜態方法。 – carnun

+0

@carnun,不,它不應該。只需在你的'GenoType'實例上調用它,例如'GenoType g = parent1.newInstance()'。如果您願意,您還可以添加參數。 –

+0

這是輝煌!謝謝約翰。解決了一個非常類似的問題,使我的代碼更好。我在一個抽象類中有最終的泛型,我的編譯器不會停止抱怨。 – Jeremy

1

你可以使用一個abstract factory pattern建議。由於您在工廠只需要一種工廠方法,這可能是一個退化的情況,但它可能是您需要的。您應該將工廠實例傳遞給您的Reproducer對象,可能作爲某種方法的參數。這不太好,但至少你現在已經抽象了對象創建。

更好的解決方案可能是改變你的架構。爲什麼不忘記Genotype課程?你的基因型表示基本上是一個基因列表。您可以在這些列表上使用(通用)操作創建實用程序類,並在其他類中使用這些操作。以下是我的意思草圖:

public static <G extends Gene> List<? extends G> mutate(List<G> genotype) { ... } 
public static <G extends Gene> List<List<? extends G>> crossover(List<G> p1, List<G> p2) { ... } 

作爲一個側面說明:有利於在聲明類類型接口類型;在你的例子中,你不使用List接口。

作爲最後一個方面:在你的例子中,你並不需要泛型。如果你聲明參數類型爲Genotype,你會得到相同的解決方案(具有相同的問題)。類型X參數接受任何類型爲X的對象(包括子類型!)作爲參數。