如何动态绑定方法引用到特征?

时间:2015-03-11 23:53:21

标签: scala traits method-reference

鉴于

def add(x: Int, y: Int): Int = x + y

val addAsMethodReference: (Int, Int) => Int = add _

trait BinaryOperator {
  def execute(x: Int, y: Int): Int
}

val addAsBinaryOperator: BinaryOperator = addAsMethodReference...?

如何在不实施addAsMethodReference 的情况下将BinaryOperator绑定到BinaryOperator

Java 8 SAM将正常运行。我可以在Java 8中使用二进制运算符trait的任何地方使用方法引用。

理想情况下,我想写一些类似的东西:

var addAsBinaryOperator: BinaryOperator = addAsMethodReference.asNewInstanceOf[BinaryOperator]

我想要这个asNewInstanceOf方法的原因是它适用于任何方法签名。我不在乎传递了多少参数。如果我必须手动执行此操作,我必须仔细匹配每个xy。这在更大范围内容易出错。

left.asNewInstanceOf[right]的规范是right方有多个抽象方法,它在编译时失败。如果left侧不是与right侧的单个抽象方法签名匹配的函数类型,则它将在编译时失败。 right方不需要是一个特征,它可以是一个抽象类,只有一个抽象方法。

2 个答案:

答案 0 :(得分:2)

好吧,你可以进行隐式转换

implicit def myConversion(f: (Int, Int) ⇒ Int): BinaryOperator = new BinaryOperator {
    def execute(x: Int, y: Int): Int = f(x, y)
  }

如果它在范围内,你可以做到

val addAsBinaryOperator: BinaryOperator = addAsMethodReference

对于返回整数的整数的任何二进制函数。虽然也许这也被归类为“手工实施”。我无法看到编译器神奇地意识到您希望将函数解释为具有某种特定结构的用户创建特征的实例的方式。

答案 1 :(得分:0)

新答案:

这就是你想要的。它动态创建BinaryOperator对象,其execute方法绑定到addAsMethodReference

def add(x: Int, y: Int): Int = x + y

val addAsMethodReference: (Int, Int) => Int = add _

trait BinaryOperator {
  def execute(x: Int, y: Int): Int
}

val addAsBinaryOperator: BinaryOperator = 
    new BinaryOperator{ def execute(x: Int, y: Int): Int = addAsMethodReference(x,y) }

老答案

这是你想要的吗?

implicit class EnhancedBinaryOperator(val self: BinaryOperator) extends AnyVal {
  def addAsMethodReference(a: Int, b: Int) = a + b
}

val o: BinaryOperator = ???    // anything here
o.addAsMethodReference(1,2)    // addAsMethodReference is now on BinaryOperator