2011-11-08 2 views
8

이것은 실제 코드를 단순화 한 예입니다. 약간의 인위적인 경우 사과드립니다. 내가 뭘하고 싶은지 효과적으로 단일 중첩 형식 인수 중 두 형식 매개 변수를 얻는 것입니다. 나는 이것이 불가능하다고 확신하지만, 나는 그 기회를 줄 것이라고 생각했다.Java의 중첩 형식 매개 변수

//Not legal java code 
public class Foo<C extends Collection<T>> { //where T is another type parameter 
    private C coll; 

    public Foo(C coll) { 
     this.coll = coll; 
    } 

    public void add(T elem){ 
     this.coll.add(elem); 
    } 
    //UPDATED TO ADD GETTER 
    /** 
    * I may need to retrieve the collection again, or pass it 
    * on to another function that needs the specific C type 
    */ 
    public C getColl(){ 
     return coll; 
    } 
} 
... 
List<String> strings = new ArrayList<String>(); 
Foo<List<String>> foo = new Foo<List<String>>(strings); 
foo.add("hello"); 

은 내가 다른 유형의 매개 변수를 추가하여 그것을 할 수 있다는 것을 알고

public class Foo<C extends Collection<T>,T> 

을하지만 내가 중복 추가해야합니다 :

Foo<List<String>,String> foo = new Foo<List<String>,String>(strings); 

그리고 내 실제 경우를, 내 generics는 때때로

public class Bar implements Baz<String> 
과 같은 implements 절에서 지정할 수 있습니다.

두 번째 유형 매개 변수가 내 얼굴에 구현 세부 사항을 던져 버린 것처럼 느끼기 때문에 두 번째 유형 매개 변수가 더욱 고통 스럽다는 것을 지정해야합니다. 말하자면

Foo<Bar,String> 

문자열과 바 사이의 관계가 이미있을 때, 그냥 우아하지 않게 보입니다. 나는 그 자바를 얻습니다, 그래서 영토와 함께 간다. 그러나 이것에 대한 해결책이 있는지 궁금해.

답변

6

불변성을 필요로하는 기존 클래스에는 아무 것도 없기 때문에 어쨌든 이상적이라고 생각하지 않습니다. 유일한 이유는 T 컬렉션의 돌연변이를 허용하는 것입니다 가지고있는 경우

Foo<T,C extends Collection<T>> 

더 일반적으로

Foo<T,C extends Collection<? super T>> 

수 있습니다. 자주 두 가지 유형의 매개 변수를 지정하는 데 대해 우려하는 경우

주, 당신이 얕은 서브 클래스 만들 수 있습니다

class DerivedFoo<T> extends Foo<Collection<T>,T> 

을하고 당신이 것을 피하기 위해 공장 방법을 사용할 수 있습니다 작성시에 두 번 지정

public static <T> Foo<Collection<T>,T> fromCollection(Collection<T> c) 

당신은 또한 interface에 추상적 인 인터페이스는 위 DerivedFoo으로 얻을 간결 유형의 이점을 얻을 수 있습니다.

+0

팩토리 메서드 아이디어는 흥미 롭습니다. 그러나 내 코드가 항상 같다고 지시하더라도 형식 메서드가 두 번 지정된다는 것은 여전히 ​​귀찮습니다. –

+0

@RusselLeggett, ok, 그러면 불변성이 필요합니다. 콜렉션 '이 필요하지 않습니까? 네. 그것은 고통입니다. 필자의 조언은 라이브러리의 복잡성을 처리하고 반환 형식이'Foo 인 팩토리가 CompleicatedFoo , T>를 확장하여 클라이언트가 단일 매개 변수 버전을 사용할 수 있도록함으로써 간결한 API를 노출하는 것입니다. –

2

왜 당신은 그냥 같이 당신의 유일한 유형 매개 변수로 T를 사용하지 것이다 :

public class Foo<T> { //where T is another type parameter 
private Collection<T> coll; 

public Foo(Collection<T> coll) { 
    this.coll = coll; 
} 

public void add(T elem){ 
    this.coll.add(elem); 
} 
+0

이것이 왜 해결책이 될지 궁금하다. – ty1824

+3

제가 말했듯이, 이것은 고의적 인 예입니다. 그러나 들어간 컬렉션의 유형이 중요 할 경우 어떻게 될까요? 목록이나 집합 또는 TreeList가 될 수 있습니다. 컬렉션을 다시 검색하기 위해 getter를 추가했다고 가정 해 봅시다. 타입이 중요 할 것입니다. –

2

이전 Java7에, 생성자는 형식 유추하지 마십시오 해결 방법은 정적 팩토리 메소드를 가지고있다. 더 이상 필요하지 않습니다. 우리가 그들 사이의 제약이 형식 매개 변수가있는 경우 자바 7에서 당신이 TC

Foo<List<String>,String> foo = new Foo<>(strings); 

에 관해서는 수, 중복 어느 정도 할 수 있었을 것입니다. 귀하의 예에서는 하나의 매개 변수 C이 다른 매개 변수 T을 완전히 지시하므로 중복성은 참을 수없는 것처럼 보입니다. 나는 해결책을 보지 못했다.

그러나 유형 매개 변수가

Foo<String,Bar> foo = new Foo<>(bar); 

그래서 우리는 첫 번째 String를 선언 순서가있는 경우 당신은 아마 더 잘 느낄 수있다; Baz<String>이 더 있습니다 Bar