双向运算符

时间:2019-01-29 22:59:44

标签: scala

给出以下n维数据点:

class Point private (private val data: Array[Double]) {

  private def op(other: Point)(f: (Double, Double) => Double): Point = {
    for (i <- data.indices)
      data(i) = f(data(i), other.data(i))
    this
  }

  private def op(scalar: Double)(f: (Double, Double) => Double): Point = {
    for (i <- data.indices)
      data(i) = f(data(i), scalar)
    this
  }

  // Point scalar ops
  def +(scalar: Double): Point = op(scalar)(_ + _)
  def -(scalar: Double): Point = op(scalar)(_ - _)
  def *(scalar: Double): Point = op(scalar)(_ * _)
  def /(scalar: Double): Point = op(scalar)(_ / _)

  // Point Point ops
  def +(other: Point): Point = op(other)(_ + _)
  def -(other: Point): Point = op(other)(_ - _)
  def *(other: Point): Point = op(other)(_ * _)
  def /(other: Point): Point = op(other)(_ / _)


  override def toString: String = {
    "Point(" + data.map(_.toString).mkString(", ") + ")"
  }
}

object Point {
  def apply(data: Double*): Point = new Point(Array(data:_*))
}

我可以执行以下操作:

val p1 = Point(1,2,3)
println(p1 + 3) // Point(4.0, 5.0, 6.0)

但是,我也希望有一种“双向”行为:

val p1 = Point(1,2,3)
println(3 + p1)

有什么方法可以在Scala中完成此操作吗?

1 个答案:

答案 0 :(得分:6)

是的,可以。使用implicit class标量值创建丰富的包装。

implicit class ScalarOps (val scalar: Double) extends AnyVal {
  def + (point: Point): Point = point + scalar
  // Other methods...
}

val p = Point(1, 2, 3)
1 + p // res0: Point = Point(2, 3, 4)

请注意,我将隐式类与value class组合在一起,因此在大多数情况下,您的包装器并未真正实例化。