Troels Blum
Troels Blum

Reputation: 855

Scala implicit type conversion and ==

Can anyone enlighten me as to why implicit type conversion does not work with ==?

Example:

class BitArray(l: Int, v: Long) {  
    val length = l  
    var value = v  
    def ==(that: BitArray) = value == that.value  
    def ==(integer: Long) = value == integer  
    def +(that: BitArray) = new BitArray(length,value+that.value )  
    def +(integer: Long) = new BitArray(length,value+integer )  
//...  
}  
object BitArray{
        implicit def longToBitArray(x : Long) = new BitArray(64,x)  
        def apply(v: Long) :BitArray = apply(64,v)  
}

Now I can do:

scala> BitArray(5) + 5  
res13: BitArray = 00000000000000000000000000001010  
scala> 5 + BitArray(5)   
res14: BitArray = 00000000000000000000000000001010  
scala> BitArray(5) == 5  
res15: Boolean = true  
scala> BitArray(5) == 6  
res16: Boolean = false  

BUT:

scala> 5 == BitArray(5)  
<console>:11: warning: comparing values of types Int and BitArray using `==' will   
always yield false  
       5 == BitArray(5)  
         ^  
res17: Boolean = false  

Upvotes: 8

Views: 2855

Answers (3)

Anonymous
Anonymous

Reputation: 841

Adding to the other answers, remember that the equals function has to be SYMMETRIC, that is (a equals b) == (b equals a).

Upvotes: 0

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297155

You are missing a fundamental aspect of Scala, which is how equality works.

Basically, all classes extending AnyRef implement the following method:

def   equals  (arg0: Any)  : Boolean   

And all classes implement the following method:

def   ==  (arg0: Any)  : Boolean

Now, you should override not ==, but equals. The method == will call equals, but Java code will use equals, not ==. This is not the cause of the problem you see, but it is important enough that I think it is worth mentioning.

Now, as to the implicit not working, remember that implicits are only looked for if there is no method that satisfy your code. However, Int's == can be compared with BitArray, as == receives an argument of type Any. Therefore, Int's equality method is called, and no implicit is looked for.

Upvotes: 15

Ben Lings
Ben Lings

Reputation: 29403

To override the == operator, you should actually override the equals method:

override def equals(other: Any): Boolean = other match {
  case ba: BitArray => value == ba.value
  case _ => false
}

You can't make an instance of your BitArray equal to a Long and still obey the equals contract (ie. it won't be symmetric).

Upvotes: 6

Related Questions