2010-08-25 14 views
6

Qualcuno può spiegarmi perché il tipo di conversione implicita non funziona con ==?Conversione di tipo implicito di scala e ==

Esempio:

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) 
} 

Ora posso fare:

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 

MA:

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 

risposta

12

Ti manca un aspetto fondamentale di Scala, ovvero il modo in cui funziona l'uguaglianza.

In sostanza, tutte le classi che si estendono AnyRef implementare il seguente metodo:

def equals (arg0: Any) : Boolean 

E tutte le classi di implementare il seguente metodo:

def == (arg0: Any) : Boolean 

Ora, si dovrebbe ignorare non ==, ma equals. Il metodo == chiamerà equals, ma il codice Java utilizzerà equals, non ==. Questa non è la causa del problema che vedi, ma è abbastanza importante che penso che sia degno di nota.

Ora, per quanto riguarda l'implicito non funziona, ricorda che gli impliciti vengono cercati solo se non esiste un metodo che soddisfi il tuo codice. Tuttavia, == di può essere confrontato con BitArray, come == riceve un argomento di tipo Any. Pertanto, viene chiamato il metodo di uguaglianza Int e non viene cercata alcuna implicita.

+0

Grazie per la risposta molto chiara :-) –

+1

Non tanto un aspetto fondamentale di Scala, ma un aspetto di come la libreria standard è fondamentalmente rotta. – Apocalisp

+2

@Apocalisp intendevo fondamentale come in "devi saperlo se vuoi usare Scala". –

6

Per ignorare l'operatore ==, si dovrebbe effettivamente sovrascrivere il metodo equals:

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

Non è possibile creare un'istanza di BitArray uguale a Long e rispettare il contratto di uguaglianza (es. non sarà simmetrico).

+0

Puoi elaborare? Oppure indicarmi la direzione di una documentazione di come funziona l'uguaglianza? Grazie –

0

In aggiunta alle altre risposte, ricordare che la funzione di uguale deve essere SYMMETRIC, ovvero (a equals b) == (b equals a).