2010-08-04 17 views
10

Ho un'enumerazione in scala mappata a stringhe in JPA. Per una codifica più confortevole, ho definito conversioni implicite tra di loro. Così ora posso definire il valore val person.role = "User", - person.role è il tipo di enumerazione a String, quindi c'è la conversione. Ma quando provo a confrontare questi due, ottengo sempre il falso, perché lo def equals (arg0: Any) : Boolean prende Any così non c'è alcuna conversione innescata. Ho bisogno di una conversione esplicita, ma il mio piano era quello di essere in grado di ometterlo, qual è la migliore pratica? soluzione più accurata qui?Confronto tra stringhe ed enumerazione

+0

Basi questa mappatura su "Enumerazione" e "Valore"? – Thomas

+0

@Thomas si sto usando scala 'scala.Enumeration' e 'scala.Enumeration.Value' – coubeatczech

+0

Qual è il contesto/caso d'uso per il confronto? La corrispondenza dei pattern può fornire una soluzione migliore, ma dipende molto da ciò che stai cercando di ottenere. –

risposta

16

Il nel Enumeration è di tipo Val. E credo che la sua implementazione di equals non confronti il ​​nome della stringa del valore. Penso che un modo pesante di fare questo è creare il tuo Enumeration e Val in modo che ritorni vero se il nome corrisponde.

Ma nel mio codice usa, non con JPA, converto sempre la stringa in MyEnumeration.Value. Questo è facile con cose come:

object E extends Enumeration { val User = Value("User") } 

scala> val a = E.withName("User") 
a: E.Value = User 

Si noti che quando si usa withName, se la stringa non corrisponde a qualsiasi nome nell'enumerazione si ottiene un'eccezione.

Poi sempre utilizzare i campi di enumerazione nei vostri confronti:

scala> a == E.User 
res9: Boolean = true 

Se JPA restituisce solo una stringa, e non c'è modo intorno ad esso. Quindi penso che l'opzione migliore sia convertire il valore in stringa e far corrispondere stringa a stringa, oppure aggiornare la stringa in una Val e confrontare Val. Il missaggio di questi tipi non funzionerà per il confronto, a meno che non si implementi un qualche tipo di estensione al metodo equals, e ciò è complicato.

13

Ampliando la risposta di Thomas, se si sta utilizzando il confronto in ramo, utilizzando pattern matching può essere più appropriato:

object Role extends Enumeration { 
    val User = MyValue("User") 
    val Admin = MyValue("Admin") 

    def MyValue(name: String): Value with Matching = 
     new Val(nextId, name) with Matching 

    // enables matching against all Role.Values 
    def unapply(s: String): Option[Value] = 
     values.find(s == _.toString) 

    trait Matching { 
     // enables matching against a particular Role.Value 
     def unapply(s: String): Boolean = 
      (s == toString) 
    } 
} 

È quindi possibile utilizzare questo come segue:

def allowAccess(role: String): Boolean = role match { 
    case Role.Admin() => true 
    case Role.User() => false 
    case _ => throw ... 
} 

o

// str is a String 
str match { 
    case Role(role) => // role is a Role.Value 
    case Realm(realm) => // realm is a Realm.Value 
    ... 
}