问题
Methods taking a single argument can be written as an infix operators in Scal. I.e. adding *(other:C) = foo(this, other)
to class C, will allow us to write c1 * c2
instead of foo(c1,c2). But is there a way to define infix operators on existing classes that you cannot modify?
E.g. if I wanted to write c1 + c2
instead of xor(c1,c2)
, where c1,c2:Array[Byte]
, I obviously cannot modify the Array-Class.
I found this and tried
implicit class Bytearray(a1:Array[Byte]) extends Anyval {
def +(a2:Array[Byte]) = xor(a1,a2)
}
But that doesn't seem to work (c1 + c2
).
Type mismatch, expected:String, actual:Array[Byte]
I thought that perhaps the issue was my using +
, so I exchanged it for xor
but c1 xor c2
only lead to
Cannot resolve symbol xor
Any suggestions?
UPDATE
Interesting. I had a class Foo
with an object Foo
defined below it, containing the implicit class. This lead to the aforementioned errors.
However, deleting the object and instead putting the implicit class into a trait BytearrayHandling
and then extending it (class Foo extends BytearrayHandling
) seems to work. Why is that?
回答1:
It should be straight forward with the normal declaration of extension methods:
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)
However be aware that sometimes you will run into this:
Type mismatch, expected:String, actual: X
This is because of an implicit conversion kicking in that allows you to +
anything by converting it to a String. I have given up trying to understand how to deactivate it. It will finally go in Scala 2.12 if I'm not mistaken.
As eugener pointed out, this error message may indicate that you haven't actually imported your extension method (implicit conversion). For example:
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
gives:
<console>:14: error: type mismatch;
found : Array[Byte]
required: String
"foo".getBytes + "bar".getBytes
^
because of this Predef
conversion. After you import MyStuff.ByteArrayOps
, it works.
回答2:
You can do something like:
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)
the last line of which should yield Array(1, 2, 3)
.
来源:https://stackoverflow.com/questions/31221462/scala-defining-own-infix-operators