谁在功能接口中实现"other methods" - 在哪里实现?



其他方法;针对消费者和非消费者<和BiFunction><T,>然后().

其他方法"Function<T,>操作符为compose(), andThen(), identity()。

其他方法"BinaryOperator<T,>andThen(), maxBy(), minBy().

其他方法"for Predicate is and(), or(), negate(), isEqual()。

其他方法"for BiPredicate<T,>Is and(), or(),否定()

既然函数接口是通过lambda表达式传递给实现方法的,那么谁来实现这些其他方法呢?

更新:我想指出的是;如果"其他方法"的语义;不是像下面评论中的例子那样琐碎或直接吗?考虑Predicate功能接口。如果我传递一个lambda表达式到一个实现方法,但and(), or(), negate()不是直截了当的。那么默认实现将不会覆盖它。我想我们将不得不处理我们自己的自定义功能接口,扩展原始接口并实现所有"其他方法"。

更新:对于像BiFunction这样的函数接口,它有andThen()其他方法,这是否意味着我们必须继承这个接口并创建一个带有默认方法andThen()的新接口?

嗯,我觉得你遗漏了一些东西。

让我们考虑Predicate接口。我删去了与问题无关的内容。

interface Predicate<T> {
boolean test(T t);
default Predicate<T> negate() {
return (t) -> !test(t);
}
}

这是一个功能接口:它只有一个抽象方法。该接口的作者还添加了一个方法,他们将其命名为negate。它的实现返回一个新的Predicate,当它的test方法被调用时返回完全相反的结果。他们添加这个方法是因为他们认为它会很有用。

可以看到,negate方法是默认的,并且有一个方法体。有主体的方法从来不是抽象的。

因为函数式接口是通过lambda表达式传递给实现方法的

如果我传递一个lambda表达式实现方法

不知道你在这里是什么意思,但我认为它的措辞很糟糕。lambda表达式只能在需要函数接口的地方使用。因此lambda表达式是函数式接口的唯一抽象方法的实现。"other"到目前为止,方法与这个故事无关。

比如说,我想创建一个Predicate来测试字符串是否等于"Hello"典型的实现可能是这样的:

str -> str.equals("Hello")

这(大致)相当于:

class PredicateImpl implements Predicate<String> {
@Override
public boolean test(String t) {
return t.equals("Hello");
}
public Predicate<String> negate() {
return new Predicate<String> {
@Override
public boolean test(String t) {
return !PredicateImpl.this.test(t);
}
};
}
}

可以看到,negate()返回一个新的谓词,该谓词捕获调用该方法的谓词,当调用其test方法时,它被延迟到捕获的谓词,并返回结果布尔值的反转。

lambda表达式永远不会实现默认方法,因为它们不是抽象的。因此,negate不会以任何方式被覆盖。


当然,这并不妨碍我们创建自己的函数接口来篡改否定的语义。

public interface MyPredicate<T> extends Predicate<T> {
@Override
public default MyPredicate<T> negate() {
return t -> true; // Say what?! That's not a negation!
}
}

现在让我们先看看"normal"谓词的作用:

String s = "Hello";
Predicate<String> stringIsHello = t -> t.equals("Hello");
Predicate<String> stringIsNotHello = stringIsHello.negate();
System.out.println(stringIsHello.test(s));
System.out.println(stringIsNotHello.test(s));

输出,如预期:

true
false

现在让我们使用自定义谓词:

String s = "Hello";
MyPredicate<String> p1 = t -> t.equals("Hello");
MyPredicate<String> p2 = p1.negate();
System.out.println(p1.test(s));
System.out.println(p2.test(s));

输出:

true
true

现在negate在我们的MyPredicate你期望它做什么?绝对不是。编译器是否阻止您实际执行此操作?不,它不能,也不会。

在再次阅读Lambdas的主题时,我有同样的问题,我回到这里,因为我不理解其他评论和答案。

我想也许答案是这样-andThen()的参数是另一个函数接口;在本例中,另一个Consumer<T>

default Consumer<T> andThen(Consumer<? super T> after)

可以用不同的lambda链接方法andThen条款

void foo(Consumer<T> consumer1Lambda, Consumer<T> consumer2Lambda) {
consumer1Lambda.test().andThen(consumer2Lambda);
}

实际上,是否需要实现该方法(或者即使可以)取决于Functional接口。例如,这里有一个BiConsumer,它实现了accept方法,然后链接了andThen方法的后续实现。

BiConsumer<Integer, Integer> mathResults = (x, y) -> System.out
.printf("Here are the results for %s op %s:%n%n", x, y, x,y);
mathResults = mathResults.andThen((x,y)->System.out.printf("Addition:       %s%n", x+y));
mathResults = mathResults.andThen((x,y)->System.out.printf("Subtraction:    %s%n", x-y));
mathResults = mathResults.andThen((x,y)->System.out.printf("Multiplication: %s%n", x*y));
mathResults = mathResults.andThen((x,y)->System.out.printf("Division:       %s%n", (double)x/y));

mathResults.accept(30,20);

打印

Here are the results for 30 op 20:
Addition:       50
Subtraction:    10
Multiplication: 600
Division:       1.5

相关内容

  • 没有找到相关文章