开发者

How to define/implement this interface with generics in a simpler way?

I'm working in a Genetic Algorithm and I want it as abstract as possible to be able to reuse the GA. I defined and implemented a Population 开发者_开发技巧Interface, and well it works, but I'm sure that's not the best way to do it. I don't have great experience with Java Generics. Is there an easier way of defining and implementing the Population interface (e.g. maybe avoid a cast conversion? avoid a new list in 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;
    }
}


Use a Bounded Wildcard in your interface:

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() {
...    
    }

}


The simplest solution is extending a list (then use addAll(...) to add a list of Chromosoms to the list):

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

But if you want the same structure I would make Population into a generic list class. That way both add... and get... methods can be handled in the generic base class. If you do want to override any other feature you just extend Population (class TSPPopulation extends Population<TSPChromosome>.

Usage:

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

Implementation:

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);
    }
}


It would be much safer if you made the Population generic itself:

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(){
        //
    }

}

That way you would not need any casting in client code.


I know GAs, and I would question whether your Population implementation actually needs to know which kind of Chromosome you put in. Do you really have different Population implementations depending on the Chromosome subclass? Or what you really want is to make sure you have the same subclass of Chromosome in a Population? In this last case, you can define the Population interface as others suggested, and the make a generic implementation (or skip the interface altogether):

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);
    }
}

Be careful not to put too many generics, or you will end up with generics hell, or tons of casts which will make generics more annoying than useful.


Yes, for instance:

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);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜