如何将操作符重新定义为函数?

时间:2017-06-07 21:03:22

标签: scala oop

我在为类创建新代码时一直在考虑停止重复自己的方法,例如,当出现同一个类时,我需要对案例类中的所有值求和。

一个例子可能更好地解释我目前正在做的事情:

case class A(a: Double, b: Double) {
    def +(that: A): A {
        A(a + that.a, b + that.b)
    }
    def *(that: A): A {
        A(a * that.a, b * that.b)
    }
}

允许我这样做:

val a = A(1, 2)
val b = A(3, 4)
val c = a + b

其中c = A(4, 6),对吧?

好吧,如果我想概括操作怎么办?例如,让我举一个例子,说明工作,但我认为完美地表达了我的意图。

case class A(a: Double, b: Double) {
    def operation(op: (x: Double, y: Double) => Double)(that: => A) = {
        A(op(a, that.a), op(b, that.b))
    }
}

现在,我知道这不起作用,因为我可能已经把一些非常重要的概念混淆了但我还没有确定,但我想出了这个想法:

val a = A(1, 2)
val b = B(3, 4)
val + = (x: Double, y: Double) => (x + y)
val res = a + b

我知道这可以通过不同的方式完成,这将获得相同的结果,但有没有办法描绘像这样的通用操作?

2 个答案:

答案 0 :(得分:2)

你可以这样做:

case class A(a: Double, b: Double) {
  def + = operation(_ + _) _
  def * = operation(_ * _) _

  private def operation(op: (Double, Double) => Double)(that: => A) =
    A(op(a, that.a), op(b, that.b))
}

答案 1 :(得分:2)

不完全确定你追求的是什么,但也许这一点很接近。

case class A(a: Double, b: Double) {
  def @@(that:A): ((Double, Double) => Double) => A =
    op => A(op(a, that.a), op(b, that.b))
}

用法:

val a = A(7, 2)
val b = A(3, 4)

(a @@ b)(_+_)      // res0: A = A(10.0,6.0)
(a @@ b)(_*_)      // res1: A = A(21.0,8.0)
(a @@ b)(Math.min) // res2: A = A(3.0,2.0)