Scala中的交换运算符定义

时间:2012-07-07 16:05:22

标签: scala

让我们说我为我的班级定义了一些运算符:

class A {
    def +(f: Float) = /* ... */
}

val a: A = new A

这样我就可以轻松完成a + 1f。如果我想让lib的用户能够写1f + a怎么办?我该如何实现呢?

2 个答案:

答案 0 :(得分:11)

在Scala 2.9中,您可以导入此隐式转换:

implicit def floatPlusAExtender (x: Float) = 
  new {
    def + (a: A) = a + x
  }

并根据需要使用它。从Scala 2.10开始,你最好像这样进行转换:

implicit class FloatPlusAExtender (x: Float) {
  def + (a: A) = a + x
}

甚至更好:

implicit class FloatPlusAExtender (val x: Float) extends AnyVal {
  def + (a: A) = a + x
}

最后一种方式称为Value Class,与前两种方式不同,它为此功能提供零开销。 (谢谢,axel22)这也是2.10

附带的新东西

或者您可以像这样修改A

class A {
  def + (x: Float) = /* ... */
  def +: (x: Float) = this + x
}

并像这样使用它:

1f +: a

最后一种方法更可取。

答案 1 :(得分:3)

一种方法是pimp-my-library-pattern

class FloatWithPlusA(f: Float) {
  def +(a: A) = a + f
}

implicit def floatPlusA(f: Float): FloatWithPlusA =
  new FloatWithPlusA(f)

val a: A = new A
a + 1.0f  /* a.+(1.0f) */
1.0f + a  /* floatPlusA(1.0f).+(a) */

另一种方法是添加一种右关联方法,但明显的缺点是两个运算符的语法各不相同:

class A {
  val f: Float = 1.0f

  def +(f: Float) = this.f + f
  def +:(f: Float) = this.f + f
}

val a: A = new A
a + 1.0f
1.0f +: a