2012-09-26 6 views
3

내 (증류) 시나리오 :공변 수집

의 내가 Interface라는 인터페이스 및 class Foo implements Interface 있다고 가정 해 봅시다.

나는 또한 iterable 물건을 수행하기 위해 컬렉션에 위임하는 일반적인 iterable "Result"클래스를 가지고있다. Result 클래스는 질문과 관련없는 다른 것들을 수행합니다. 그래서 :

class Result<E> implements Iterable<E> { 

    private Collection<E> delegate; 

    public Result(Collection<E> delegate) { 
     this.delegate = delegate; 
    } 

    public Iterator<E> iterator() { 
     return delegate.iterator(); 
    } 

    // ... other irrelevant stuff. 
} 

Result 개체의 사용자가 몇 가지 요소 후 반복하는 중지 할 가능성이 높다 (하지만 난 얼마나 많은 통제 할 수 없음) 동안, 잠재적으로 거대한 수 있습니다 Result에 전달 컬렉션입니다.

그럼 다른 클래스가 있는데, 내부적으로 Foo의 컬렉션을 보유하고 있지만 Result를 반환 할 수 있어야하는 Query라고 부르 자.

class Query { 
    private Collection<Foo> data; 

    public Result<Interface> getAllData() { 
     return new Result<Interface>(new ArrayList<Interface>(data)); 
    } 

    // EDIT: Not all Result objects are of Interfaces. 
    public Result<SomeUnrelatedInterface> getSomeOtherData() { 
     return ...; 
    } 
} 

그래서 getAllData은 (AN ArrayList<Interface> 등) 데이터의 사본을 받아, 통과 그 위양을위한 새로운 Result에 : 현재 다음과 같습니다. 그 컬렉션은 아마 거대하고 결과의 수신자는 아마도 처음 몇 가지 결과 만 필요하기 때문에 이것은 나에게는 이상적이지 않습니다.이

사람이 내가 구체적인 수집의 사본을 취할 필요가 없습니다 그런 일을 변경하는 방법을 생각할 수 : 질문에 대한 지금

?

이상적으로, 나는 Result 생성자가 public Result(Collection<? extends E> delegate) (Collection 같은 대부분의 할) 수있는, 그리고 어떻게 든 Collection<E>에 해당 모음을 적용해야하지만 그게 어떻게 보이는지 알아낼 수 없었던 것입니다.

+0

누구나 내가 더 좋은 제목을 제안 할 수 있다면, 나는 그것을 감사 할 것입니다. :). – Martin

+0

반복되는 동안 결과를 보유한 컬렉션이 변경됩니까? 스냅 샷을 반환하는 것이 중요합니까? – Vitaliy

+0

아니요, 모음이 변경되지 않습니다. 메소드가 스냅 샷을 리턴해야하는 경우,이를 관리하기 위해서는 분명히 'Query' 객체가 있어야합니다 (사본을 가져 와서 데이터를 다르게 관리하는 등). – Martin

답변

1

여러분도 알다시피, Collection<? extends E>Collection<E>으로 바꾸는 위험은 이제 발신자가 E을 넣을 수 있다는 것입니다. 그래서 너는 그것을 배제해야하고 너는 괜찮을거야. Collections.unmodifiableCollection(Collection) 만 있으면 그 결과가 Collection<E>으로 표시됩니다.

편집 :

Collection<? extends Interface> foos = new ArrayList<Foo>(); 
Collection<Interface> adapted = Collections.unmodifiableCollection(foos); 
+0

E는 인터페이스입니다. 그 의도는 호출자가 구현 방식에 상관하지 않기 때문에 모든 E를 포함하기를 원합니다. 호출자는'Foo'에 대해 전혀 모릅니다. – Martin

+1

@ 마틴 나는 내 대답을 고쳤다. 나는 인터페이스가 어떻게이 모든 것으로 해석되는지 정말로 모른다. –

+0

아, 죄송합니다. 나는 당신의 초기 문장을 잘못 읽었습니다! 호출자가 응답을 수정하는 것을 원하지 않기 때문에, 변경 불가능한 것을 갖는 것은 많은 의미를가집니다. 나는 이것이 Query 메소드의 반환 유형을 변경하지 않아도되는 것을 좋아한다. (사실 내 케이스에서는 상당히 큰 변화가 될 것이다. - Query는 실제로 많은 구현체를 가진 인터페이스이며, 각기 다른 구현체를 처리한다. 기본 데이터 유형). – Martin

3

겠습니까 당신을 위해 확인을 다음과 같은 변형?

class Result<E extends Interface> 
implements Iterable<E> { 

    private Collection<E> delegate; 

    public Result(Collection<E> delegate) { 
     this.delegate = delegate; 
    } 
    public Iterator<E> iterator() { 
     return delegate.iterator(); 
    } 
} 
class Query { 
    private Collection<Foo> data; 

    public Result<? extends Interface> getAllData() { 
     return new Result<Foo>(data); 
    } 
} 
+0

+1, 오 이런 - 나는 그 생각을하지 못했다니 믿을 수가 없어. 나는 내 문제를 해결할 것이라고 생각한다. 감사! – Martin

+0

나는 이것이 나의 필요를 충족시키는 지 확인했다. 참고 : E는 인터페이스를 확장 할 필요가 없지만 솔루션에 영향을주지 않고 첫 번째 줄에서 제약 조건을 제거 할 수 있습니다. – Martin

+1

이것은 문제를 길 아래로 밀어내는 것입니다. 어떤 점에서'Result 를'Result '이되도록 확장합니다. –