简体   繁体   English

实例化抽象类的泛型扩展

[英]Instantiating a generic extension of an abstract class

Trying to write some generalised code for Genetic Algorithms and I have an abstract class Genotype as follows: 试图为遗传算法编写一些通用代码,我有一个抽象类基因型如下:

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

//...
}

This class is intended to be extended and the subclass obviously provides the implementation of getPhenotype() and mutate(). 该类旨在扩展,子类显然提供了getPhenotype()和mutate()的实现。 However, I also have a second class that takes two Genotype objects as parameters and returns an ArrayList containing Genotype objects. 但是,我还有一个第二个类,它接受两个Genotype对象作为参数,并返回一个包含Genotype对象的ArrayList。 Since I don't know the type of the extended Genotype objects at this point I need to use a generic parameter as follows: 由于此时我不知道扩展的Genotype对象的类型,我需要使用泛型参数,如下所示:

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

However, since I need to return two objects of type G in an ArrayList I clearly have a problem where I can't instantiate the new Genotype objects because they're 1. generic types and presumably 2. abstract. 但是,由于我需要在ArrayList中返回两个G类型的对象,我显然遇到了一个问题,我无法实例化新的Genotype对象,因为它们是1.泛型类型,大概是2. abstract。

This might be a bad way of going about things all together but if anyone has a solution that would be great. 这可能是将所有事情放在一起的坏方法,但如果有人有一个很好的解决方案。 Thank you. 谢谢。

I would suggesting using a factory method in your Genotype class 我建议你在Genotype类中使用工厂方法

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

You could use an abstract factory pattern . 您可以使用抽象工厂模式 Since you need only one factory method in your factory this is arguably a degenerate case, but it might be what you need. 由于您的工厂只需要一种工厂方法,这可以说是一种退化的情况,但它可能就是您所需要的。 You should pass the factory instance to your Reproducer object, probably as a an argument of some method. 您应该将工厂实例传递给Reproducer对象,可能作为某种方法的参数。 It's not pretty, but at least you now have abstraction over object creation. 它并不漂亮,但至少你现在拥有对象创建的抽象概念。

A better solution would probably be to change your architecture. 更好的解决方案可能是改变您的架构。 Why not forget about the Genotype class? 为什么不忘记Genotype类呢? Your genotype representation is basically a list of genes. 您的基因型表示基本上是基因列表。 You could make a utility class with (generic) operations on these lists and use these operations in your other classes. 您可以在这些列表上创建具有(通用)操作的实用程序类,并在其他类中使用这些操作。 The following is a sketch of what I mean: 以下是我的意思草图:

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

As a side note: favour declaring interface types over class types; 作为旁注:赞成在类类型上声明接口类型; in your example you don't use the List interface. 在您的示例中,您不使用List接口。

As a final side note: in your example you don't really need the generic type. 最后一点注意:在您的示例中,您并不真正需要泛型类型。 If you declare the parameter types as Genotype you get the same solution (with the same problem). 如果将参数类型声明为Genotype则会得到相同的解决方案(具有相同的问题)。 A type X parameter accepts any object of type X (including subtypes!) as argument. 类型X参数接受任何类型为X的对象(包括子类型!)作为参数。

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

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