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 - 定义自己的中缀运算符的主要内容,如果未能解决你的问题,请参考以下文章