2014-10-31 2 views
6

아래 예제 코드에서 chainWanted 메서드와 같이 BiFunctions를 연결하고 싶습니다.BiFunctions를 체인화하는 방법은 무엇입니까?

BiFunction은 AndThen의 매개 변수로 Function을 사용합니다. 어떻게 든 BiFunctions를 연결할 수 있습니까?

여기의 코드는 컴파일되지 않아 BiFunction을 함수로 캐스팅 할 수 없습니다.

import java.util.function.BiFunction; 
import java.util.function.Function; 

import org.openqa.selenium.remote.RemoteWebDriver; 

public class Wf { 

    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> init = this::init; 
    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> wait = this::wait; 

    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainNow = init 
      .andThen(d -> { 
       System.out.println("--------------"); 
       return null; 
      }); 

    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = init 
      .andThen((BiFunction) wait); 

    public RemoteWebDriver init(RemoteWebDriver d, WfParams params) { 
     System.out.println("init(d, params)"); 
     return d; 
    } 

    public RemoteWebDriver wait(RemoteWebDriver d, WfParams params) { 
     System.out.println("Wf.wait(d, params)"); 
     return d; 
    } 

    public static void main(String[] args) throws Exception { 
     new Wf().start(); 
    } 

    private void start() { 
     chainNow.apply(null, null); 
    } 
} 
+0

두 가지 기능을 시작할 수있는 체인을 연결하는 방법을 알지 못합니다. bifunction의 결과는 하나의 인수입니다. 어떻게 다른 인수로 연결하려고합니까? – fge

답변

0

는 어디 WfParams는 wait의 호출을위한에서 온 것인가? 모든 함수 호출에 동일한 WfParams를 재사용하려는 경우 WfParams를 각 함수에 전달하는 대신 클래스 멤버 변수로 지정하면됩니다.

class Wf { 
    private final WfParams params; 

    public Wf(WfParams params) { 
     this.params = params; 
    } 

    UnaryOperator<RemoteWebDriver> init = this::init; 
    UnaryOperator<RemoteWebDriver> wait = this::wait; 

    Function<RemoteWebDriver,RemoteWebDriver> chain = init.andThen(wait); 

    RemoteWebDriver init(RemoteWebDriver d) { 
     // can use WfParams here 
     return d; 
    } 

    RemoteWebDriver wait(RemoteWebDriver d) { 
     // can use WfParams here    
     return d; 
    } 

    private void start() { 
     chain.apply(null); 
    } 

    public static void main(String[] args) { 
     new Wf(new WfParams()).start(); 
    } 
} 

이와 같은 기능 체인을 사용하려는 특별한 이유가 있습니까? 왜 init(...); wait(...);start()에서 전화하지 않으시겠습니까?

3

첫 번째 함수의 반환 값이 다음 함수의 인수로 전달되고 해당 함수의 반환 값이 후속 함수에 인수로 전달되는 등 자연스럽게 작동합니다. 이것은 두 개의 인수를 취하기 때문에 BiFunction과 자연스럽게 작동하지 않습니다. 첫 번째 인수는 이전 함수의 반환 값이지만 두 번째 인수는 무엇입니까? 또한 BiFunction이 왜 andThen과 체인 연결을 허용하는지 다른 이유는 BiFunction 대신 Function입니다.

그러나 두 번째 인수에 값을 제공하는 방법이 있다면 BiFunction을 다른 것으로 연결할 수 있음을 알 수 있습니다. 두 번째 인수의 값을 로컬 변수에 저장하는 도우미 함수를 만들어이 작업을 수행 할 수 있습니다. 그런 다음 BiFunction은 환경 변수를 캡처하여 두 번째 인수로 사용하여 Function으로 변환 할 수 있습니다.

다음과 같이 표시됩니다.

BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = this::chainHelper; 

RemoteWebDriver chainHelper(RemoteWebDriver driver, WfParams params) { 
    return 
     init.andThen(rwd -> wait.apply(rwd, params)) 
      .apply(driver, params); 
} 

// ... 

chainWanted.apply(driver, params); 

chainHelper 방법에 대해서는 캡처에 대한 params 인수를 보유하고 있습니다. 연쇄 작업을 수행하기 위해 init.andThen()이라고 부릅니다. 그러나 이것은 Function을 요구하는 반면, waitBiFunction입니다. 대신에있어서 참조 this::wait을 사용하는 우리는 사전 환경에서 params 캡처 람다 식을

rwd -> wait.apply(rwd, params) 

사용. 단일 인수를 사용하여 단일 값을 반환하는 람다 식을 제공하므로 (BiFunction)을 래핑하는 Function이됩니다. 이것은 부분 신청 또는 의 예입니다. 마지막으로 apply()을 사용하여 결과를 BiFunction이라고하고 원래 인수를 전달합니다.

관련 문제