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

Posted

技术标签:

【中文标题】Scala - 定义自己的中缀运算符【英文标题】:Scala - defining own infix operators 【发布时间】:2015-09-22 03:51:04 【问题描述】:

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

例如如果我想写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)。

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

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

无法解析符号异或

有什么建议吗?

更新

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

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

【问题讨论】:

隐式类必须是某种对象的一部分,您必须导入它。如果您发布您尝试过的完整代码,也会有所帮助。 为什么“某种对象”不能是伴生对象(请参阅上面的编辑)?对我来说没有多大意义。 可以,但您仍然需要在使用隐式的上下文中导入它。 【参考方案1】:

你可以这样做:

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)

【讨论】:

【参考方案2】:

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

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

这是因为隐式转换开始了,它允许您通过将其转换为字符串来+ 任何东西。我有givenuptryingto 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 之后,它就可以工作了。

【讨论】:

你确定不能用+吗?请参阅我的答案(至少对我而言!):) 我使用的是 Scala 2.11.6。 这不是不可能的,如果您需要另一个隐式转换,它可能只是被阻止。我更新了文本。

以上是关于Scala - 定义自己的中缀运算符的主要内容,如果未能解决你的问题,请参考以下文章

28.scala的运算符

Scala - 中缀与点符号

Scala Operators, File & RegExp

在 Scala 中将中缀转换为后缀表示法

如何使用 lua 构建中缀 TO 前缀函数

在 R 中,如何确定用户定义的中缀运算符的运算符优先级?