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

3

在Scala中,只有一个参数的方法可以被写成中缀运算符。例如,将*(other:C) = foo(this, other)添加到类C中,就可以使用c1 * c2代替foo(c1,c2)。但是,有没有一种方法可以定义现有类上的中缀运算符,而又不能修改该类呢?

例如,如果我想用c1 + c2代替xor(c1,c2),其中c1,c2:Array[Byte],我显然无法修改Array-Class。

我找到了这个并尝试了一下。

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

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

类型不匹配,期望:String,实际:Array[Byte]

我想也许问题出在使用了 +,所以我将其替换为 xor,但是 c1 xor c2 只导致了

无法解析符号xor

有什么建议吗?

更新

有趣的是,我有一个定义了隐式类的 class Foo 和一个定义在其下方的 object Foo。这导致了上述错误。

然而,删除该对象并将隐式类放入一个 trait BytearrayHandling 中,然后扩展它 (class Foo extends BytearrayHandling) 似乎可以工作。为什么会这样呢?


1
隐式类必须是某种对象的一部分,然后您需要导入它。如果您能发布您尝试的完整代码,那将会很有帮助。 - Eugene Ryzhikov
为什么“某种对象”不能成为伴生对象(请参见上面的编辑)?这对我来说没有太多意义。 - User1291
1
可以,但你仍然需要在隐式被使用的上下文中导入它。 - Eugene Ryzhikov
2个回答

8

使用常规的扩展方法声明应该很直观:

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)

然而请注意,有时您会遇到这种情况:

类型不匹配,期望:String,实际:X

这是因为隐式转换会启动,允许您通过将其转换为字符串来使用 + 运算符。我已经 尝试 放弃 理解 如何停用它。如果我没记错的话,它最终会出现在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 后,它就能工作了。

1
你确定不能使用+吗?看看我的回答,它对我有用!:) 我正在使用Scala 2.11.6。 - bjfletcher
1
这并非不可能,只是如果您需要进行其他隐式转换,则可能会被阻止。我更新了文本。 - 0__

2
您可以尝试以下操作: ```html

您的内容

```
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)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接