使用Java 8函数式接口编写代码

3

我有一个像这样的Java-8-FunctionalInterface:

@FunctionalInterface
public interface A {
    void doIt ();
}

Function接口提供了compose方法。我想使用它来简化一个类型为A的流,如下所示:

Stream<A> as;
A composed = as.reduce (() -> {}, Function::compose);

作为结果,我希望有一个函数 A,它调用每个流中的 AdoIt 方法。
composed.doIt (); // Executes every doIt ()

但是因为A不是Function的实现者,所以在那里无法使用方法引用Function::compose。 我不能继承自Function(或Supplier),因为那样我会有两个抽象方法(我的和Function中的)。我该怎么做才能使我的函数由A组成呢?

1
do 不是 Java 中的有效标识符。 - fabian
你的问题有点不清楚 - 你只是想要 as.forEach(A::do) 吗? - assylias
@fabian:我改正了这个问题,我把代码减少得太多了;-) 但那不是问题所在。 - F. Böller
我想要一个A对象。稍后我想用a.doIt()调用它。它的执行应该导致对Stream中所有A的doIt的调用。 - F. Böller
1个回答

7

没有理由要求compose方法必须来自于Function接口。对于你的情况,Function接口不适用,因为Function有一个返回值(而不是void),并且它的compose方法旨在将一个函数的结果馈送到下一个函数中。

只需创建自己的compose方法即可:

@FunctionalInterface
public interface A {
  void doIt ();
  default A compose(A next) {
      return () -> { doIt(); next.doIt(); };
  }
}

然后您可以按照预期操作:
Stream<A> as=…;
A composed = as.reduce (() -> {}, A::compose);

请注意,由于您的接口具有与Runnable相同的语义,因此您甚至可以将其设置为Runnable的子接口,以允许混合使用RunnableA
@FunctionalInterface
public interface A extends Runnable {
    default void doIt() { run(); }
    default A compose(Runnable next) {
      return () -> { doIt(); next.run(); };
  }
}

好的,我没有想到那个。 但是我希望Java能够识别A是一个FunctionalInterface,并在需要时将其视为Function的实现,这样我就不需要重复compose的实现了。 - F. Böller
1
@F. Böller:但是你的接口不是一个“函数”。一个“函数”具有“T->R”签名,而你的接口具有“()->()”签名。它们不兼容。 - Holger
1
+1 这是基本正确的,因为Java是静态类型的,它的函数接口也是静态类型的,所以执行函数组合的运算符也必须是静态类型的。一个小细节:在Function中使用的约定是f.compose(g)类似于f(g()),它先应用g再应用f。而andThen方法则相反。 - Stuart Marks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接