【问题标题】:@FunctionalInterface inheritance@FunctionalInterface 继承
【发布时间】:2018-04-20 12:08:34
【问题描述】:

假设我有以下界面:

@FunctionalInterface
public interface First {
   int fun(int a);
}

还有

@FunctionalInterface
public interface Second extends First {
   default int fun(int a) { fun(a, a); }

   int fun(int a, int b);
}

然后,如果我在某处有一个采用First 的方法,我可以这样做,例如:

methodThatTakeFirst(val -> val + 1);

但我也希望能够传递Second,例如:

methodThatTakeFirst((v1, v2) -> v2 * v2);

但是,这只有在我像这样转换 lambda 时才有效:

methodThatTakeFirst((Second) (v1, v2) -> v2 * v2);

我的问题是:有没有办法设计这种模式而不必将 lambda 转换为子接口?或者处理这种情况的最优雅的方式是什么?

【问题讨论】:

  • ...您为什么要这样做?这有什么用?为什么不在函数式接口中定义 default 函数来处理额外的行为,而不是强加看似不必要的继承?
  • 没有强制转换,编译器无法推断您想要Second 的 lambda 实现。强制转换是告诉编译器的最好/最简单的方法,所以强制转换 处理这种情况的最优雅的方式。
  • @Makoto 好点,假设 First 来自一个无法更改但扩展的库
  • 即使First 无法更改,通过Second 的实现,尤其是lambda 可以得到什么?方法methodThatTakeFirst() 唯一可以合理地使用其参数做的事情是调用fun(int a) 方法,该方法在Second 中是默认的。你最好定义一个First 的具体实现,并传递一个普通的实例。
  • 有时我想传递一个同时使用两个参数的 lambda,有时只有一个

标签: java java-8 functional-interface


【解决方案1】:

您可以重载methodThatTakeFirst,以便它也接受Second 的实例作为参数,并委托methodThatTakeFirst(First first)

void methodThatTakeFirst(First first) {
    // play with first
}

void methodThatTakeFirst(Second second) {
    methodThatTakeFirst((First) second); // casting necessary
}

演员表至关重要,因此编译器实际上会委托给methodThatTakeFirst(First first),否则您最终会得到StackOverflowError

这是否是一个好的设计,我不知道,但我认为它超出了这个问题的范围。

【讨论】:

    【解决方案2】:

    也许只是添加另一个 lambda?

      void secondMethod(Second second) {
          methodThatTakeFirst(x-> second.fun(x,x)); 
      }
    

    【讨论】:

      猜你喜欢
      • 2015-04-19
      • 2012-10-30
      • 2017-12-27
      • 2014-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多