2017-09-16 19 views
3

다음과 같은 문제가있었습니다. 메서드는 2 개의 인수를 취하는 이중 함수를 사용해야합니다. 하나는 Collection<T> 유형이고 다른 하나는 T입니다. 실제 함수는 실제로는 Collection::remove 또는 Collection::add 일 수 있습니다. 실제 함수는 12 개 이상의 콜렉션에 사용되며 여러 가지 유형의 값과 콜렉션이 함수에 있습니다.메서드 정의에서 일반 BiFunction을 사용하여이 작업을 수행 할 수 있습니까?

는 처음에는들이 generic 없었다 - 단지 Collection<String>의가 있었다 요소 BiFunction<Collection<String>, String, Boolean> 그냥 잘 작동으로 String의 너무 인수를 선언했다 :

List<String> idCodes; 
void visitElement(Element e, 
        BiFunction<Collection<String>, String, Boolean> elementOp) { 
    elementOp.apply(idCodes, e.getIdCode()); 
} 

을 그러나 나는 너무 컬렉션의 다른 유형을 추가하고, 발견

List<String> idCodes; 
List<Integer> weights; 

void visitElement(Element e, 
        BiFunction<...> elementOp) { 
    elementOp.apply(idCodes, e.getIdCode()); 
    elementOp.apply(weights, e.getWeight()); 
} 

을했지만 실패 - 난 그냥 상관없이 내가 사용하는 어떤 한 장소 또는 다른 오류를 컴파일 얻을 수있다 : 나는 더 이상 일반적으로 BiFunction를 사용하는 방법을 찾을 수 d는 유형 매개 변수에 대해 실패합니다. 내 시도

하나는 Collection::add에 전달할 때 실제로 Collection<String>String에 기능을 적용 할 때

<T> void visitElement(Element e, 
         BiFunction<Collection<T>, T, Boolean> elementOp) 

이 아닌 실패했다; 또는 Collection<Integer>int.

은 그 때 나는 다른 인터페이스 제작 :

interface ElementOp { 
    <T> boolean apply(Collection<T> collection, T item); 
} 

을 내가 원하는대로 그리 놀라 울이는 지금 정확히 작동합니다. 따라서 내 질문은 :

난 정말

interface ElementOp { 
    <T> boolean apply(Collection<T> collection, T item); 
} 

void visitElement(Element e, 
        ElementOp elementOp) { 
    elementOp.apply(idCodes, e.getIdCode()); 
    elementOp.apply(weights, e.getWeight()); 
} 

를 사용해야합니까 또는이 사건에 대한 BiFunction를 사용하여 어떻게 든 가능한 것입니까?

P. 나는 이클립스 4.3 화성 자바 컴파일러를 사용하고있다. 그래서 약간의 버그로 인해 작동하지 않을 수도있다.

답변

2

두 가지 경우 (StringInteger)를 모두 처리하는 T 일반을 사용하는 BiFunction을 사용할 수 없습니다. BiFunction

<T> void visitElement(Element e, 
     BiFunction<Collection<T>, T, Boolean> elementOp) { 
    ... 
    elementOp.apply(idCodes, e.getIdCode()); 
    elementOp.apply(weights, e.getWeight()); 
} 

는 일반적인 클래스와 함수의 인수로 Collection<T>T와 함께 파라미터 :

이 코드는 컴파일되지 않을 수 있습니다. 당신이 두 번째에 Collection<String>String 주먹 통화 및 Collection<Integer>Integer을 통과하면서
그래서 당신은 단지 Collection<T>T 객체/변수를 전달할 수 있습니다.이 사용자 정의 인터페이스와


는 상황이 다르다 :

interface ElementOp { 
    <T> boolean apply(Collection<T> collection, T item); 
} 

이 작동 :

elementOp.apply(idCodes, e.getIdCode()); 
elementOp.apply(weights, e.getWeight()); 

BiFunction에 반하는로 매개 변수로 모든 클래스에 선언 된 변수를 수용 할 수있다.
유지해야 할 점은 ElementOp이 제네릭 클래스가 아니라는 것입니다.
T은 실제로 전달 된 인수의 형식 유형을 유추하는 메서드 범위 범용입니다.


귀하의 요구 사항을 해결하려면 여러 번에 동일한 방법 ( Collection.add() 또는 Collection.remove())를 호출하지만, 다른 유형 ( String 또는 Integer)의 인수와 함께, 당신은 일반적인 BiFunction<T,Collection<T>, Boolean> 사용하지 않습니다.
소개 한 사용자 지정 기능 인터페이스가 훨씬 적합합니다.

2

음의 첫 번째 시도가 작동하지 않았다 때문에이 같은이있을 때 :

<T> void visitElement(Element e, BiFunction<Collection<T>, T, Boolean> elementOp) { 
    // some code   
} 

모든 T 유형은 다음에 대해 그 visitElement 알고; elementOpBiFunction<Collection<T>, T, Boolean>입니다. T은 컴파일러에 의해 추론됩니다.

여기에 다른 interface을 소개 할 이유가 없습니다. 간단히 방법을 변경할 수 있습니다. 또한 어쨌든 결과를 사용하지 않기 때문에 내가 BiConsumer하지 BiFunction를 사용한 것을 알 수 :

void visitElement(T value, BiConsumer<Collection<T>, T> elementOp, Collection<T> elements) { 
     elementOp.accept(elements, value); 
} 

을 그리고 그것을 사용 :

BiConsumer<Collection<String>, String> bi = Collection::remove; 

    Element e = ... 
    Collection<String> idCodes...; 
    visitElement(e.getIdCode(), bi, idCodes);