Scala - 定义自己的中缀运算符

Scala - defining own infix operators

采用单个参数的方法可以写成 Scal 中的中缀运算符。 IE。将 *(other:C) = foo(this, other) 添加到 class C,将允许我们编写 c1 * c2 而不是 foo(c1,c2)。但是有没有一种方法可以在您无法修改的现有 classes 上定义中缀运算符?

例如如果我想写 c1 + c2 而不是 xor(c1,c2),其中 c1,c2:Array[Byte],我显然不能修改 Array-Class.

我找到了 this 并尝试了

implicit class Bytearray(a1:Array[Byte]) extends Anyval {
    def +(a2:Array[Byte]) = xor(a1,a2)
}

但这似乎不起作用 (c1 + c2)。

Type mismatch, expected:String, actual:Array[Byte]

我认为可能是我使用 + 的问题,所以我将其换成了 xor 但是 c1 xor c2 只会导致

Cannot resolve symbol xor

有什么建议吗?

更新

有意思。我有一个 class Foo,下面定义了一个 object Foo,包含隐含的 class。这会导致上述错误。

但是,删除对象并将隐式 class 放入 trait BytearrayHandling 然后扩展它 (class Foo extends BytearrayHandling) 似乎工作。这是为什么?

您可以这样做:

class ByteArray(self: Array[Byte]) {
  def +(other: Array[Byte]) = Array[Byte](1, 2, 3) // replace with your code
}

implicit def byteArrayPlus(self: Array[Byte]) = new ByteArray(self)

Array[Byte](0, 1, 2) + Array[Byte](0, 2, 3)

最后一行应该产生 Array(1, 2, 3)

扩展方法的正常声明应该是直截了当的:

implicit class ByteArrayOps(private val a1: Array[Byte]) extends AnyVal {
  def + (a2: Array[Byte]): Array[Byte] = 
    (a1 zip a2).map { case (x, y) => (x ^ y).toByte }
}

"foo".getBytes + "bar".getBytes  // Array(4, 14, 29)

但是请注意,有时您会 运行 进入以下内容:

Type mismatch, expected:String, actual: X

这是因为隐式转换的启动允许您 + 将任何内容转换为字符串。我有 given up trying to understand 如何停用它。如果我没记错的话,它最终会出现在 Scala 2.12 中。

正如 eugener 所指出的,此错误消息可能表明您尚未实际导入扩展方法(隐式转换)。例如:

object MyStuff {
  implicit class ByteArrayOps(private val a1: Array[Byte]) extends AnyVal {
    def + (a2: Array[Byte]): Array[Byte] = 
      (a1 zip a2).map { case (x, y) => (x ^ y).toByte }
  }
}

"foo".getBytes + "bar".getBytes  // error

给出:

<console>:14: error: type mismatch;
 found   : Array[Byte]
 required: String
              "foo".getBytes + "bar".getBytes
                                     ^

因为这个 Predef 转换。在你import MyStuff.ByteArrayOps之后,它起作用了。