2011-10-05 1 views
1

는 유전자 알고리즘에 대한 몇 가지 일반화 된 코드를 작성하려고 노력하는 추상 클래스의 일반적인 확장을 인스턴스화 다음과 같이 나는 추상 클래스의 유전자형을 가지고

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를 반환하는 두 번째 클래스도 있습니다. 내가 ArrayList에 내가 명확 타입 G의 두 개체를 반환해야하기 때문에,

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

을하지만 :이 시점에서 확장 된 유전자형 개체의 유형을 알고하지 않기 때문에 나는 다음과 같이 일반적인 매개 변수를 사용해야합니다 제노 타입 객체를 인스턴스화 할 수 없다는 문제가 있습니다. 왜냐하면 그것들은 제네릭 타입 일 겁니다.

이것은 모든 것을 함께 모으는 나쁜 방법 일 수 있습니다. 그러나 누군가가 훌륭한 솔루션을 갖고 있다면. 고맙습니다.

답변

3

나는 당신이 abstract factory pattern를 사용할 수 귀하의 Genotype 클래스

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

고마워요, 이건 정적 인 방법일까요? 분명히 나는 ​​추상적 인 정적 메서드를 가질 수 없다. – carnun

+0

@carnun, 안됩니다. 'GenoType' 인스턴스에서 호출하십시오 (예 :'GenoType g = parent1.newInstance()'). 원하는 경우 인수를 추가 할 수도 있습니다. –

+0

이것은 기쁜 소식입니다! 요한 감사합니다. 아주 비슷한 문제를 해결하고 코드 100 배를 향상 시켰습니다. 나는 추상 클래스에서 generics의 최종 배열을 가지고 있었고 컴파일러는 불평하는 것을 멈추지 않을 것이다. – Jeremy

1

를 팩토리 메소드를 사용하여 제안한다. 공장에서 하나의 팩토리 메소드 만 필요하기 때문에 이것은 아마도 퇴보 사례이지만, 필요한 것일 수 있습니다. 팩터 리 인스턴스를 Reproducer 객체에 전달해야합니다. 이는 아마도 일부 메소드의 인수 일 수 있습니다. 그것은 꽤 아니지만 적어도 당신은 지금 객체 생성에 대한 추상화를 가지고 있습니다.

더 나은 해결책은 아키텍처를 변경하는 것입니다. 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의 모든 오브젝트 (부속 유형! 포함)를 인수로 허용합니다.