2012-06-24 3 views
0

과 트릭이 필요 이건 내 코드입니다 :객체 작성자

public interface InterfaceA<J>{ 
    // … 
} 

public interface InterfaceB extends InterfaceA<String> { 
    // … 
} 

public interface InterfaceC extends InterfaceA<Long>{ 
    // … 
} 

public class Creator<J, I extends InterfaceA<J>> {} 

public abstract class Base<J, J1> implements InterfaceA<J> {  
    protected Creator<J, J1> creator;  

    protected Base() { 
     creator=ObjectCreator.createCreator(); 
    } 
} 

public class Extension1 extends Base<Integer> implements InterfaceB { 
    // … 
} 

public class Extension2 extends Base<Double> implements InterfaceC { 
    // … 
} 

내가 Creator<Double, interfaceC>을 가지고 Creator<Integer, InterfaceB>Extension2을 가지고 Extension1를 원한다. 패턴을 봐? Creator<T1, T2> 여기에서 T1은 직접적인 부모의 유형이고 T2은 상기 클래스에 의해 구현 된 인터페이스입니다. 이 일을 할 수있는 방법이 있습니까? 아무도 ObjectCreator.createCreator() 코드를 말할 수 있습니까?

는 지금 내 코드는 다음과 같습니다 : 내 모든 코드를 통해 오류를 가지고

public class ObjectCreator { 
    public static <J, I extends InterfaceA<J>> Creator<J, I> createCreator() { 
     return new Creator(); 
    } 
} 

. 나는 정말로 혼란 스럽다. 내가 여기서 무엇을 놓치고 있니? 중요성의 특정한 순서에

package scratch; 

interface InterfaceA<J> { 
    // … 
} 

interface InterfaceB extends InterfaceA<String> { 
    // … 
} 

interface InterfaceC extends InterfaceA<Long> { 
    // … 
} 

class Creator<J, I extends InterfaceA<J>> { 
} 

abstract class Base<J, I extends InterfaceA<J>> { 
    protected Creator<J, I> creator; 

    protected Base(Class<J> jClass, Class<I> iClass) { 
     creator = ObjectCreator.createCreator(jClass, iClass); 
    } 
} 

class Extension1 extends Base<String, InterfaceB> implements InterfaceB { 
    protected Extension1() { 
     super(String.class, InterfaceB.class); 
    } 
} 

class Extension2 extends Base<Long, InterfaceC> implements InterfaceC { 
    protected Extension2() { 
     super(Long.class, InterfaceC.class); 
    } 
} 

class ObjectCreator { 
    public static <J, I extends InterfaceA<J>> Creator<J, I> 
    createCreator(Class<J> jClass, Class<I> iClass) { 
     return new Creator(); 
    } 
} 

:

+0

처음에는이 코드가 구문 상 올바른가요? 왜냐하면 나는 약간의 키워드가 코드를 컴파일하기 위해 빠져 있다고 생각하기 때문이다. – chaosguru

+0

SO에 업로드하기 전에 코드를 올바르게 확인하십시오. 제네릭은 제대로 사용되지 않습니다. 선 보호 된 창조자 창조자; 의미가 없으며 코드가 올바른 구문을 필요로합니다. – chaosguru

+0

예, 죄송합니다. 여는 대괄호로 "less than"을 모두 변경하기 위해 편집 할 때 실수로 삭제해야합니다. –

답변

0

당신이 놓친 물건의 전체 무리는 컴파일 버전은 다음과 같이 보일 것이다있다

  • 당신은 서명 된 클래스가있을 때 createCreator()처럼, 형식 토큰으로 Class 개체를 전달해야합니다. Java 컴파일러는 반환 값을 할당 할 변수의 유형에 따라 유형을 유추 할 수 없습니다. 게다가, 당신은 어쨌든 타입 소거 때문에 그것들을 원한다. 그렇지 않으면 주어진 타입에 따라 Creator을 특화시킬 수 없다.
    • 두 개의 유형 매개 변수가있는 이있는 경우 확장 클래스는 두 유형 매개 변수를 모두 사용해야합니다.
    • 확장 클래스 서명이 이상했습니다. Creator<Integer, InterfaceA<String>>을 가질 수 없기 때문에 class Extension1 extends Base<Integer, InterfaceA<String>>을 가질 수 없습니다. createCreator()에 명시적인 형식 토큰을 사용하면 오류가 덜 신비스럽고 어디에서나이 제약 조건을 전파해야합니다. BaseJI 형식 매개 변수 사이의 제약 조건과 독립적으로 만들 수는 없습니다.
+0

실제로 매개 변수로 .class를 사용하지 않으려합니다. 그래서 내가 원하는 걸 얻기 위해 피할 수 없다는 말을하는거야? Java는 이것을 지원하지 않습니까? 예, 타입 소거는 항상 귀찮은 것입니다. 태양의 사람들은 솔루션을 만들어서 Java의 generics가 .net만큼 강력 할 수 있을까요? –

+0

유형 보증인이되기를 원한다면 유형 토큰을 전달하지 않아도됩니다. 실제로 Java와 .NET 제네릭 간의 주요 차이점 중 하나는 .NET에서 형식 매개 변수를 형식 토큰으로 직접 사용할 수 있다는 것입니다. 반대로 유형 토큰, Class.cast() 및 기타 런타임을 사용하여 Java generics가 "지원하지 않는"작업을 수행 할 수 있습니다. – millimoose

+0

다른 질문에 관해서 : 그들은 결코하지 않을 것입니다. Java generics의 디자인은 "힘"에 대한 하위 호환성을 위해 의식적으로 결정되었습니다. .NET을 사용하는 접근 방식은 제네릭을 사용하기 위해 오래된 API를 "갱신"하는 것을 불가능하게한다는 단점이 있습니다. 그래서'System.Collections'을 생성하는 대신'System.Collections.Generic'을 생성해야했습니다. 이 곳이 보여주는 곳은 리피터 컨트롤이 일반적인 것이 아니며 일반적인 방법으로 만들 수없는 ASP.NET입니다. 유일한 해결책은 v4.5의'.aspx' 컴파일러 해킹과 C# 이후 8 년 (!)입니다. 2.0 및 제네릭. – millimoose