【问题标题】:Scala - defining own infix operatorsScala - 定义自己的中缀运算符
【发布时间】: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) 似乎可行。这是为什么呢?

【问题讨论】:

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

标签: scala operators implicit-conversion infix-notation infix-operator


【解决方案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。
    • 这不是不可能的,如果您需要另一个隐式转换,它可能只是被阻止。我更新了文本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    相关资源
    最近更新 更多