2010-11-29 14 views
1

私は遺伝的アルゴリズムに取り組んでおり、私はGAを再利用できるようにできるだけ抽象的にしたいと思っています。 Population Interfaceを定義して実装してもうまく動作しますが、それを行う最良の方法ではないと確信しています。私はJava Genericsに大きな経験はありません。定義し、人口のインタフェースを実装する簡単な方法があります(例えば、多分キャスト変換を避ける)(getChromosomesで新しいリストを避けるため?)ジェネリックでこのインタフェースをより簡単に定義/実装する方法は?

public interface Population 
{ 
    void addChromosomes(List<? extends Chromosome> chromosomes); 

    List<Chromosome> getChromosomes(); 

    // More code here ... 
} 

public class TSPPopulation implements Population 
{ 
    private List<TSPChromosome> chromosomes; 

    @Override 
    public void addChromosomes(List<? extends Chromosome> chromosomes) { 
     for (Chromosome chromosome : chromosomes) { 
      this.chromosomes.add((TSPChromosome) chromosome); 
     } 
    } 

    @Override 
    public List<Chromosome> getChromosomes() { 
     List<Chromosome> newList = new ArrayList<Chromosome>(); 
     for (TSPChromosome chromosome : chromosomes) { 
      newList.add(chromosome); 
     } 
     return newList; 
    } 
} 
+1

古き良きAI、数年前にこれに似たコードを書いたことを覚えています。 –

答えて

7

をお使いのインタフェースで有界ワイルドカードを使用します。

public interface Population<T extends Chromosome>{ 
    void addChromosomes(List<T> chromosomes); 

    List<T> getChromosomes(); 
} 

public class TSPPopulation implements Population<TSPChromosome> 
{ 
    private List<TSPChromosome> chromosomes; 

    @Override 
    public void addChromosomes(List<TSPChromosome> chromosomes) { 
... 
    } 

    @Override 
    public List<TSPChromosome> getChromosomes() { 
...  
    } 

} 
+0

これらの機能をインターフェイスに実装しないでください(たとえば、クラスにするなど)。 – dacwe

+0

@dacwe:わかりませんでしたか? (あなたはインターフェースで何も実装することはできませんが、これはあなたが意味するものではありません) – Ralph

+0

私は、 'addChromosoms(..)'と 'getChromosoms()'の両方を抽象基本クラスで処理できることを意味しました。 (私の解決策を参照してください) – dacwe

2

最も簡単な解決策は、リスト(そのリストにChromosomsのリストを追加するaddAll(...)を使用)拡張されています

class Population<T extends Chromosome> extends ArrayList<T> { 
} 

をしかし、あなたは同じ目をしたい場合私はPopulationを一般的なリストクラスにします。このようにして、add...get...メソッドの両方をジェネリックベースクラスで処理できます。あなたが他の機能を無効化したいなら、あなただけのPopulationclass TSPPopulation extends Population<TSPChromosome>を拡張

使用法:。

public static void main(String... args) { 
    Population<TSPChromosome> tspPopulation = new Population<TSPChromosome>(); 
    ... 
} 

実装:インスタンスの

class Population<T extends Chromosome> { 

    private List<T> chromosomes = new ArrayList<T>(); 

    public void addChromosomes(List<T> chromosomes) { 
     this.chromosomes.addAll(chromosomes); 
    } 

    public List<T> getChromosomes() { 
     return new ArrayList<T>(this.chromosomes); 
    } 
} 
+0

リストを拡張することは、非常に単純だが効果的な解決策のように聞こえる。ありがとう! –

+0

はい、おそらくあなたが探していた解決策です! :) – dacwe

+0

私はおそらく私のGAを過度に複雑に思っています。しかし、これは私のために働いている:ラルフによって提案されたような人口インタフェース。 public abstract class BasicPopulation extends ArrayList は、集団を実装します

0

はい、:

public interface Population<T extends Chromosome> 
{ 
    void addChromosomes(List<T> chromosomes); 

    List<T> getChromosomes(); 

    // More code here ... 
} 

public class TSPPopulation implements Population<TSPChromosome> 
{ 
    private List<TSPChromosome> chromosomes; 

    @Override 
    public void addChromosomes(List<TSPChromosome> chromosomes) { 
     this.chromosomes.addAll(chromosomes); 
    } 

    @Override 
    public List<TSPChromosome> getChromosomes() { 
     return new ArrayList<TSPChromosome>(chromosomes); 
    } 
} 
1

あなたが集団そのものを作成した場合はもっと安全です:

public interface Population<T extends Chromosome> { 

    void addChromosomes(List<T> chromosomes); 

    List<T> getChromosomes(); 

} 

public class TspPopulation implements Population<TspChromosome>{ 

    @Override 
    public void addChromosomes(List<TspChromosome> chromosomes){ 
     // 
    } 

    @Override 
    public List<TspChromosome> getChromosomes(){ 
     // 
    } 

} 

これで、クライアントコードにキャスティングする必要はありません。

1

私はガスを知っている、と私はあなたのPopulation実装が実際にあなたが入れChromosomeの種類を知っておく必要があるかどうかを疑問でしょう。あなたが本当にChromosomeサブクラスに応じて、異なるPopulation実装を持っていますか?または、あなたが本当に望むのは、同じサブクラスのChromosomePopulationにあることを確認することです。この最後の場合には他の人が示唆したように、あなたはPopulationインタフェースを定義することができ、および一般的な実装を作る(または完全インタフェースをスキップ):

public class PopulationImpl implements Population<T extends Chromosome> { 
    private List<T> chromosomes; 

    @Override 
    public void addChromosomes(List<T> chromosomes) { 
     this.chromosomes.addAll(chromosomes); 
    } 

    @Override 
    public List<T> getChromosomes() { 
     return new ArrayList<T>(chromosomes); 
    } 
} 

は、あまりにも多くのジェネリックを入れないように注意してください、またはあなたがなってしまいますジェネリック地獄、またはジェネリック薬を役に立つよりも厄介なものにするたくさんのキャストで。

+0

あなたは完全に正しいです、私は染色体インターフェースを必要としません、ちょうど染色体クラスで十分です。私は時には物事を過度に複雑化する傾向があります。ありがとう –

関連する問題