简体   繁体   English

如何以更简单的方式定义/实现泛型接口?

[英]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. 我正在研究遗传算法,我希望它尽可能抽象,以便能够重用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. 我没有Java泛型的丰富经验。 Is there an easier way of defining and implementing the Population interface (eg maybe avoid a cast conversion? avoid a new list in getChromosomes() ?) 有没有更简单的方法来定义和实现人口接口(例如,避免强制转换?避免在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): 最简单的解决方案是扩展列表(然后使用addAll(...)将Chromosoms列表添加到列表中):

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

But if you want the same structure I would make Population into a generic list class. 但是,如果您想要相同的结构,则可以将“ Population变成一个通用列表类。 That way both add... and get... methods can be handled in the generic base class. 这样,可以在通用基类中处理add...get...方法。 If you do want to override any other feature you just extend Population ( class TSPPopulation extends Population<TSPChromosome> . 如果您确实想覆盖任何其他功能,则只需扩展Populationclass 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? 我知道GA,并且我会问您的“ Population实施方案是否实际上需要知道您所放入的哪种Chromosome 。根据“ Chromosome子类,您是否真的有不同的“ Population实施方案? Or what you really want is to make sure you have the same subclass of Chromosome in a Population ? 或者,您真正想要的是确保Population具有相同的Chromosome子类? In this last case, you can define the Population interface as others suggested, and the make a generic implementation (or skip the interface altogether): 在后一种情况下,您可以按照其他建议的方式定义“ 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);
    }
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM