实例化抽象类的通用扩展

发布于 2024-12-08 10:52:14 字数 1751 浏览 0 评论 0原文

尝试为遗传算法编写一些通用代码,我有一个抽象类 Genotype,如下所示:

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。因为我现在不知道扩展 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;
    }
}

但是,由于我需要在 ArrayList 中返回两个 G 类型的对象,所以我显然有一个问题,我可以' t 实例化新的 Genotype 对象,因为它们是 1. 通用类型,并且大概是 2. 抽象的。

这可能是一个糟糕的方式来解决所有问题,但如果有人有一个解决方案那就太好了。谢谢。

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(). However, I also have a second class that takes two Genotype objects as parameters and returns an ArrayList containing Genotype objects. Since I don't know the type of the extended Genotype objects at this point I need to use a generic parameter as follows:

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.

This might be a bad way of going about things all together but if anyone has a solution that would be great. Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嗼ふ静 2024-12-15 10:52:14

我建议在您的 Genotype 类中使用工厂方法

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

I would suggesting using a factory method in your Genotype class

public abstract class Genotype {
     public abstract GenoType newInstance();
}
裸钻 2024-12-15 10:52:14

您可以使用抽象工厂模式。由于您的工厂中只需要一种工厂方法,这可以说是一种退化情况,但它可能正是您所需要的。您应该将工厂实例传递给您的 Re Producer 对象,可能作为某种方法的参数。这并不漂亮,但至少你现在对对象创建有了抽象。

更好的解决方案可能是更改您的架构。为什么不忘记 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 类型的任何对象(包括子类型!)作为参数。

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. 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? 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.

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). A type X parameter accepts any object of type X (including subtypes!) as argument.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文