2013-11-20 8 views
4

이 질문에 불쾌한 영어는 죄송합니다.제네릭 팩토리에 대한 제네릭 및 형식 유추

구체적인 팩토리 인스턴스 클래스에 의해 구현 된 목록에 정의 된 클래스 인스턴스 만 만들 수있는 일종의 팩토리를 만드는 것을 염두에 둡니다. 첫째,이 인터페이스 정의 :

public interface ValuesSystem { 

    public interface AllowedValue<T extends Class<? extends SystemValue>>{}; 

    AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id); 

    Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues(); 

    <T extends SystemValue> T create(AllowedValue<Class<T>> allowedClass, ValueData data) throws InvalidValueException; 
} 

인터페이스 AllowedValue는 "허용"클래스 인스턴스를 정의하는 제네릭을 사용하여 단지 "마커 래퍼"인터페이스를 내 공장에서 만들 수 있습니다.

getAllowedValue는이 인터페이스를 구현하는 구체적인 클래스의 내부 열거 형을 사용하여 허용 된 클래스 "목록"에서 래핑 된 허용 된 Class 인스턴스를 가져 오는 데 사용되는 메서드입니다 (구체적인 클래스의 예가 올 것이다).

create 메소드는 allowedClass 인수에 지정된 허용 된 Class 인스턴스의 인스턴스를 최종적으로 작성하기위한 것입니다. 여기

이 인터페이스를 구현하는 구체적인 클래스의 예는 다음과 같습니다 순간 방법을 만들 수는 null를 들어

public class BasicValueSystem implements ValuesSystem { 

    public BasicValueSystem() { 
     super(); 
     allowedValues = (Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>) getAllowedValues(); 
    } 

    public static enum VALUES_ID { 
     MODIFIER 
    } 

    private static Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowedValues; 

    private class BasicAllowedValue<T extends Class<? extends SystemValue>> 
      implements AllowedValue<Class<? extends SystemValue>> { 

    } 

    @Override 
    public <T extends SystemValue> T create(
      AllowedValue<Class<T>> allowedClass, ValueData data) 
       throws InvalidValueException { 
     if (!(allowedClass instanceof BasicAllowedValue)) { 
      throw new InvalidValueException(); 
     } 
     return null; 
    } 

    @Override 
    public AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id) { 
     return allowedValues.get(id); 
    } 

    @Override 
    public Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues() { 
     Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowed = new EnumMap<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>(VALUES_ID.class); 
     allowed.put(VALUES_ID.MODIFIER, new BasicAllowedValue<Class<ModifierValue>>()); 
     return allowed; 
    } 
} 

을하지만, 문제는 다른 곳에 내 질문

의이없는 점 문제는 다음 코드를 사용하여 "allowed"값 인스턴스 중 하나의 인스턴스를 만들려고 할 때 발생합니다.

BasicValueSystem bvs = new BasicValueSystem(); 
AllowedValue<Class<? extends SystemValue>> allowed = bvs 
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER); 
bvs.create(allowed, new ModifierValueData()); 

컴파일러에서 알려줍니다 :

제네릭이 일반적으로 만든 유추형에 대해서는 놓친 것 같습니다.

누구나이 방법으로 서명 생성 방법을 적용 할 수 없다고 설명 할 수 있습니까?

시간을내어 미리 감사드립니다.

+0

난 정말 여기 VALUES_ID' 열거'의 역할을 이해하지 않습니다 이런 식으로 일을 할 때도 작동합니다. 현재 'allowedValues'지도에는 하나의 항목 만 있습니다. 조금 설명 할 수 있니? BTW, 왜 당신은 자신의 수업을 일반화하지 않습니까? –

+0

예에서이 함수에는 고유 한 열거 형 값이 하나 있습니다. 단순화하는 것입니다. 열거 형과 EnumMap은 EnumMap에 대해 여러 값 (열거 형의 경우)과 AllowedValue 객체를 포함하기위한 것입니다. – Mirouf

+0

그래서 항목을지도에 추가하려면 열거 형 values ​​()를 반복합니까? 'getAllowedValues'가 실제로 어떻게 보이는지 그냥 게시 할 수 있습니까? –

답변

3

public interface AllowedValue<T extends Class<? extends SystemValue>>은별로 의미가 없습니다. T의 유일한 유효한 유형은 Class 클래스가 최종이며 서브 클래스를 가질 수 없으므로 Class<? extends SystemValue>입니다. 따라서 의미를 변경하지 않고 interface AllowedValue<Class<? extends SystemValue>>으로 바꿀 수는 있지만 실제로 의미하는 것 (imho)은 interface AllowedValue<T extends SystemValue>입니다. 형식 서명에 Class을 붙이지 마십시오. 인터페이스는 여전히 Class<T>을 참조하는 메소드를 가질 수 있습니다.

public interface ValuesSystem { 

    public interface AllowedValue<T extends SystemValue>{}; 

    AllowedValue<? extends SystemValue> getAllowedValue(Enum<?> id); 

    public <T extends SystemValue> T create 
        (AllowedValue<T> allowedClass, ValueData data); 
} 

는 구현 그에 따라, BasicAllowedValue
private class BasicAllowedValue<T extends SystemValue> implements AllowedValue<T> 

는 그 다음 사용하여 코드에 문제가 사라하게 적응.

BasicValueSystem bvs = new BasicValueSystem(); 
AllowedValue<? extends SystemValue> allowed = bvs 
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER); 
bvs.create(allowed, new ModifierValueData()); 

이 컴파일됩니다. AllowedValue이 방법이없는 마커 인터페이스를 유지해야하는 경우에만,이 불필요하다고


참고 Class<T> 이미이 역할을 수행한다.

public interface ValuesSystem { 
    Class<? extends SystemValue> getAllowedValue(Enum<?> id); 
    public <T extends SystemValue> T create(Class<T> allowedClass, ValueData data); 
} 

BasicValueSystem bvs = new BasicValueSystem(); 
Class<? extends SystemValue> allowed = bvs 
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER); 
bvs.create(allowed, new ModifierValueData()); 
+0

고마워요, 제 직업은 제 실수를 이해하는 것입니다. 시간 내 주셔서 감사합니다. – Mirouf