我想链接BiFunctions,就像下面代码示例中的方法chainWanted
一样。
BiFunction将Function作为AndThen的参数。有可能以某种方式链接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 :(得分:6)
将一个Function
链接到另一个自然起作用,因为第一个函数的返回值作为参数传递给下一个函数,并且该函数的返回值作为参数传递给后续函数,因此向前。这与BiFunction
无关,因为它们有两个参数。第一个参数是前一个函数的返回值,但第二个参数是什么?它还解释了为什么BiFunction
允许andThen
与Function
而不是BiFunction
进行链接。
然而,这表明如果有某种方式为第二个参数提供值,则可以将一个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
来进行链接。但这需要wait
,而BiFunction
是this::wait
。我们使用lambda表达式
rwd -> wait.apply(rwd, params)
params
从词汇环境中捕获Function
。这给出了一个lambda表达式,它接受一个参数并返回一个值,所以它现在是一个wait
,它包裹BiFunction
BiFunction
。这是部分应用或 currying 的示例。最后,我们使用apply()
调用生成的{{1}},并传递原始参数。
答案 1 :(得分: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()
?
答案 2 :(得分:0)
我做了这样的事情-创建了我的自定义BiFunction。 这个想法是:
返回类型与第二个参数相同
第一个参数在内部传递给链接的biFunction
public interface BiFunctionCustom<T, U> extends BiFunction<T,U,U> {
default BiFunctionCustom<T, U> andThen(BiFunctionCustom<T, U> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(t, apply(t, u));
}
}