Scala - defining your own infix operators
Methods that take one argument can be written as infix statements in Scal. That is, adding *(other:C) = foo(this, other)
C to the class will allow us to write c1 * c2
instead of foo (c1, c2). But is there a way to define infix statements for existing classes that you cannot change?
eg. if i wanted to write c1 + c2
instead of xor(c1,c2)
where c1,c2:Array[Byte]
, i obviously cannot change the Array class.
I found this one and tried
implicit class Bytearray(a1:Array[Byte]) extends Anyval {
def +(a2:Array[Byte]) = xor(a1,a2)
}
But that doesn't work ( c1 + c2
).
Type mismatch expected: String, Actual: Array [Byte]
I thought maybe the problem was what I was using +
, so I exchanged it for xor
but c1 xor c2
only results in
Cannot resolve symbol xor
Any suggestions?
UPDATE
Interesting. I had class Foo
with object Foo
, defined below, containing an implicit class. This leads to the above errors.
However, deleting the object and adding the implicit class in trait BytearrayHandling
and then extending it ( class Foo extends BytearrayHandling
) seems to work. Why is this?
source to share
It should be straight forward with normal extension method declarations:
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, remember that sometimes you run into this:
Type mismatch, expected: String, actual: X
It has to do with implicit translation, which allows you to do +
anything by converting it to String. I'm up try to understand how to deactivate it. It will finally go into Scala 2.12 if I'm not mistaken.
As eugenger pointed out, this error message could indicate that you did not actually import 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 transformation Predef
. Then import MyStuff.ByteArrayOps
he works.
source to share
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 matter Array(1, 2, 3)
.
source to share