实例化抽象类的通用扩展
尝试为遗传算法编写一些通用代码,我有一个抽象类 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我建议在您的
Genotype
类中使用工厂方法I would suggesting using a factory method in your
Genotype
class您可以使用抽象工厂模式。由于您的工厂中只需要一种工厂方法,这可以说是一种退化情况,但它可能正是您所需要的。您应该将工厂实例传递给您的 Re Producer 对象,可能作为某种方法的参数。这并不漂亮,但至少你现在对对象创建有了抽象。
更好的解决方案可能是更改您的架构。为什么不忘记
Genotype
类呢?您的基因型表示基本上是基因列表。您可以创建一个实用程序类,对这些列表进行(通用)操作,并在其他类中使用这些操作。以下是我的意思的一个概述:作为旁注:优先声明接口类型而不是类类型;在您的示例中,您不使用
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: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.