你不是在讨论,而是在执行部分功能应用程序.这些操作是相关的,但不相同. Currying意味着改变你的Consumer2< T1,T2>到函数< T1,Consumer1< T2>>.将该curried函数应用于T1值时,您将获得您的方法实际执行的操作.
使用已建立的名称绑定更容易,因为将值绑定到函数的参数是一种事情,每个开发人员都能理解,而无需深入了解函数式编程的世界.
也就是说,最好记住现在接口可以有静态方法,因此不需要这样的实用程序类.此外,只返回其参数的静态方法本身几乎没有用,所以你可以将它与它应该服务的后续方法融合在一起.然后,它实现了与实例方法相同的目的,并且可以作为简单的重载提供:
@FunctionalInterface
public interface Consumer2 {
void accept(T1 t1, T2 t2);
default Consumer1 bind(T1 t1) {
return bind(this, t1);
}
static Consumer1 bind(Consumer2 super T, ? super U> c, T t) {
return u -> c.accept(t, u);
}
}
public interface Consumer1 extends Consumer {}
public class MyClass {
public static void printStrings(String a, String b) {
System.out.println(a + ": " + b);
}
public static void main(String[] args) {
Consumer2.bind(MyClass::printStrings, "hello").accept("world");
}
}
另一方面,当您使用现有标准接口Consumer和BiConsumer时,您别无选择,只能在与这些接口不同的类中提供实用程序方法.但好消息是,解决方案很容易,因为除了静态方法之外你不能提供任何其他方法:
class FunctionUtil {
static Consumer bind(BiConsumer super T, ? super U> c, T t) {
return u -> c.accept(t, u);
}
}
public class MyClass {
public static void printStrings(String a, String b) {
System.out.println(a + ": " + b);
}
public static void main(String[] args) {
FunctionUtil.bind(MyClass::printStrings, "hello").accept("world");
}
}