首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建与子类相同类型的对象

创建与子类相同类型的对象
EN

Stack Overflow用户
提问于 2013-05-05 13:10:05
回答 4查看 900关注 0票数 1

我正在设计一个遗传算法库,目前正在构造Genome类。这个类包括几种用于创建、突变、杂交和评估基因组的方法,并且将是这个库的中心。这个抽象类有两个子类StaticGenomeVariableGenome。这些类为固定或可变长度的基因组提供了额外的功能。

最终,任何两个基因组的杂交都应该独立于基因组类型。也就是说,singlePointCrossover(Genome parent2)方法接受两个基因组,并返回一个新的Genome对象,该对象是两个父基因组的特殊组合。但是,因为Genome是一个抽象类,所以我不能实例化一个新的Genome对象,因为它是它的后代。

如何从超类返回与子类相同类型的新对象?

任何帮助都将不胜感激。

Genome类:

代码语言:javascript
复制
public abstract class Genome <ElementType> {
    private String name;
    private List<AbstractGenomeElement<ElementType> > elements;

    // Mutation Methods //////////////////////////////////////////////
    public AbstractGenomeElement<ElementType> mutateElement(AbstractGenomeElement<Integer> element) {
        return this.mutateElementAtIndex(this.getElements().indexOf(element));
    }

    public AbstractGenomeElement<ElementType> mutateElementAtIndex(int i) {
        return this.getElement(i).mutate();
    }

    // Crossover Methods //////////////////////////////////////////////
    public Genome<ElementType> singlePointCrossover(Genome<ElementType> genome2){
        return multiPointCrossover(genome2, 1);
    }

    public Genome<ElementType> twoPointCrossover(Genome<ElementType> genome2){
        return multiPointCrossover(genome2, 2);
    }

    public Genome<ElementType> multiPointCrossover(Genome<ElementType> genome2, int crosses){
        List<AbstractGenomeElement<ElementType>> newElements= new ArrayList<AbstractGenomeElement<ElementType>>();
        Integer nums[] = new Integer[length-1];

        for (int i = 0; i < length-1; i++) { nums[i] = i+1; }

        List<Integer> shuffled = Arrays.asList(nums);
        Collections.shuffle(shuffled);
        shuffled = shuffled.subList(0, crosses);
        boolean selectFromParentA = true;
        for(int i = 0; i < length; i++){
            if(shuffled.contains((Integer)i)){
                selectFromParentA = !selectFromParentA;
            }
            if(selectFromParentA) newElements.add(this.getElement(i));
            else newElements.add(genome2.getElement(i));
        }
        // Code fails at this point. "Can not instantiate the type Genome"
        return new Genome<ElementType>(name, newElements);
    }
}

这两个子类:

代码语言:javascript
复制
public class StaticGenome<ElementType> extends Genome<ElementType> {

}

public class VariableGenome<ElementType> extends Genome<ElementType> {

}

我用来测试的主要方法是:

代码语言:javascript
复制
public static void main(String [] args){
    Genome<IntegerElement> genomeA = new StaticGenome<IntegerElement>("Genome A", 50);
    Genome<IntegerElement> genomeB = new StaticGenome<IntegerElement>("Genome B", 50);

    Genome<IntegerElement> offspring = genomeB.uniformCrossover(genomeA.elementCrossover(genomeA.multiPointCrossover(genomeB, 3)));
    offspring.setName("Offspring");
    System.out.println(offspring);
}
EN

回答 4

Stack Overflow用户

发布于 2013-05-05 13:58:35

您可以在抽象类中引入以下方法,并在子类中实现它。

代码语言:javascript
复制
protected abstract Genome<ElementType> newInstance(String name, List<AbstractGenomeElement<ElementType>> elements);

当子类实现这一点时,它们可以返回正确的实例。即:他们自己类型的一个新实例。在你的交叉方法中,你可以调用这个方法而不是做'new Genome‘

票数 3
EN

Stack Overflow用户

发布于 2013-05-05 13:30:44

你可以从一个被覆盖的方法返回一个子类,这叫做协变返回类型

代码语言:javascript
复制
abstract class Genome {
    abstract Genome singlePointCrossover(Genome parent2); 
}

class StaticGenome extends Genome {
    @Override
    StaticGenome singlePointCrossover(Genome parent2) {
        ...
    }
}

class VariableGenome extends Genome {
    @Override
    VariableGenome singlePointCrossover(Genome parent2) {
        ...
    }
}
票数 1
EN

Stack Overflow用户

发布于 2013-05-05 14:05:00

如果我没记错,问题是:给定一些Genome对象(这将是抽象类Genome的某个子类),我们如何实例化该子类的新实例?

好吧,我不知道这是不是最好的方法,但这是我想出来的:

代码语言:javascript
复制
public Genome<ElementType> 
multiPointCrossover(Genome<ElementType> genome2, int crosses){
    // Snip...
    Genome g;
    try {
        g = genome2.getClass()
                .getConstructor(String.class, List.class)
                .newInstance();
    } catch (Exception e) {
        // Can throw quite a few exceptions...
    }
    return g;
}

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getConstructor(java.lang.Class...) http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)

备注:我认为Dev Blanked的解决方案更干净、更简单。这就是我在他们发帖子时想出来的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16381606

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档