2013-11-23 3 views
2

이 기간 동안 나는 일종의 추상화가 필요한 프로젝트를 진행하고 있지만 java generics 및 형식 유추와 관련된 몇 가지 문제를 해결하는 방법을 모르겠습니다.제네릭을 사용하여 Java에서 유추를 입력 할 때의 문제

이 소스 코드의 단순화 된 아키텍처 :

public abstract class BaseDataset 
{ 
    // Some data 
    // Some methods 
} 

public class DerivedDataset1 extends BaseDataset 
{ 
    // Some data 
    // Implementations of some BaseDataset methods 
    // Some additional methods 
} 

public class DerivedDataset2 extends BaseDataset 
{ 
    // Some data 
    // Implementations of some BaseDataset methods 
    // Some additional methods 
} 

public interface BaseMeasure<T extends BaseDataset> 
{ 
    public float evaluate(T dataset); 
} 

public class DerivedMeasure1 implements BaseMeasure<DerivedDataset1> 
{ 
    @Override 
    public float evaluate(DerivedDataset1 dataset) 
    { 
     // evaluate some measure using DerivedDataset1 methods 
     return the evaluated measure; 
    } 
} 

public class DerivedMeasure2 implements BaseMeasure<DerivedDataset2> 
{ 
    @Override 
    public float evaluate(DerivedDataset1 dataset) 
    { 
     // evaluate some measure using DerivedDataset2 methods 
     return the evaluated measure; 
    } 
} 

public class SocialNetworkBuilder 
{ 
    public <T extends BaseDataset> void build(T dataset, BaseMeasure<T> measure) 
    { 
     float weight = measure.evaluate(dataset); 

     // ... 
    } 
} 

내 문제는 내 메인 클래스에서, 나는 이런 식으로 뭔가를 작성하는 경우이다 :

public class Application 
{ 
    public static void main(String [] args) 
    { 
     BaseDataset dataset = new DerivedDataset1(); 
     BaseMeasure<? extends BaseDataset> measure = new DerivedMeasure1(); 
     SocialNetworkBuilder socialNetworkBuilder = new SocialNetworkBuilder(); 
     socialNetworkBuilder.build(dataset, measure); 
    } 
} 

이클립스 나에게 오류를 제공 : "(BaseDataset, BaseMeasure) 인수에 대해 SocialNetworkBuilder 메소드 빌드 (T, BaseMeasure)를 적용 할 수 없습니다."

제가 생각하는 문제는 "빌드"메소드 h 나는 이런 식으로 뭔가를 할 경우 데이터 세트 및 측정 동일한 유형의 T.

으로되어 있는지 확인하려면 같이

public class Application 
{ 
    public static void main(String [] args) 
    { 
     BaseDataset dataset = new DerivedDataset1(); 
     BaseMeasure<? extends BaseDataset> measure = new DerivedMeasure1(); 
     SocialNetworkBuilder socialNetworkBuilder = new SocialNetworkBuilder(); 
     socialNetworkBuilder.build((DerivedDataset1) dataset, (DerivedMeasure1) measure); 
    } 
} 

작동,하지만 난 이런 식으로 내 문제를 해결할 수없는 내가 돈 때문에 컴파일 타임에 내 "데이터 세트"및 "측정"인스턴스의 파생 된 유형을 알지 못합니다. "dataset"및 "measure"는 런타임에 제공된 일부 매개 변수에 따라 인스턴스화되어야합니다.

런타임에 내 "계수"및 "데이터 집합"변수를 인스턴스화해야하고 해당 변수에 대해 "빌드"메서드를 호출 할 수 있어야합니다.

이 문제를 해결할 수있는 방법이 있습니까?

감사합니다.

답변

2

응용 프로그램이 다음과 같이 변경하면 컴파일 :

public class Application 
{ 
    public static void main(String [] args) 
    { 
     DerivedDataset1 dataset = new DerivedDataset1(); 
     BaseMeasure<DerivedDataset1> measure = new DerivedMeasure1(); 
     SocialNetworkBuilder socialNetworkBuilder = new SocialNetworkBuilder(); 
     socialNetworkBuilder.build(dataset, measure); 
    } 
} 
+0

답장을 보내 주셔서 감사합니다. 이 방법으로 변경하면 응용 프로그램이 컴파일된다는 것을 알지만 사용자 매개 변수에 따라 일부 특정 클래스로 기본 클래스를 측정해야합니다. – JohnQ

+0

일반 사항은 컴파일시 평가됩니다. 실제 유형 대신 기본 유형을 사용하면 컴파일러는 두 유형이 모두 '호환 가능'하다는 것을 알 수 없습니다. 그래서 제네릭없이 여기에서 시도해야한다고 생각합니다. 제네릭 사용의 이점은 무엇입니까? – isnot2bad

+0

제네릭의 유일한 이점은 구체적인 파생 측정을 통해 올바른 파생 데이터 세트를 얻을 수 있다는 것입니다. 그것이 그들에게 중요한가? – isnot2bad

1

난 당신의 코드에 아무 문제가 없다 생각합니다. 원칙적으로 올바르지 만 형식 유추는 BaseMeasure<DerivedDataset1>DerivedDataset1 extends BaseDataset 사이의 전이 유형 종속성을 처리 할만큼 강력하지 않습니다.

예를 들어 스칼라에서는 원래 코드가 작동합니다.

object DataSet extends App { 

    abstract class BaseDataset 

    class DerivedDataset1 extends BaseDataset 

    class DerivedDataset2 extends BaseDataset 

    trait BaseMeasure[T <: BaseDataset] { 
     def evaluate(dataset:T):Float 
    } 

    class DerivedMeasure1 extends BaseMeasure[DerivedDataset1] { 
     override def evaluate(dataset: DerivedDataset1) = 0 
    } 

    class DerivedMeasure2 extends BaseMeasure[DerivedDataset2] { 
     override def evaluate(dataset: DerivedDataset2) = 1 
    } 

    class SocialNetworkBuilder { 
     def build[T <: BaseDataset](dataset: T, measure:BaseMeasure[T]) : Unit = { 
      val weight = measure.evaluate(dataset); 
      println(weight) 
     } 
    } 

    val dataset1 = new DerivedDataset1() 
    val measure1 = new DerivedMeasure1() 
    val dataset2 = new DerivedDataset2() 
    val measure2 = new DerivedMeasure2() 
    val socialNetworkBuilder = new SocialNetworkBuilder() 
    socialNetworkBuilder.build(dataset1, measure1) 
    socialNetworkBuilder.build(dataset2, measure2) 
}