2010-08-04 9 views
10

J'ai une énumération dans scala mappée à des chaînes dans JPA. Pour un codage plus confortable, j'ai défini les conversions implicites entre eux. Donc, je peux maintenant définir la valeur val person.role = "User", - person.role est le type d'énumération une chaîne de sorte qu'il y a la conversion. Mais quand j'essaie de comparer ces deux, je reçois toujours faux, parce que le def equals (arg0: Any) : Boolean prend Any alors il n'y a aucune conversion déclenchée. J'ai besoin d'une conversion explicite, mais mon plan était de pouvoir l'omettre, que pensez-vous être la meilleure pratique? solution la plus propre ici?Comparaison chaîne et énumération

+0

Basez-vous ce mapping sur 'Enumeration' et 'Value'? – Thomas

+0

@Thomas oui j'utilise scala 'scala.Enumeration' et 'scala.Enumeration.Value' – coubeatczech

+0

Quel est le contexte/cas d'utilisation pour la comparaison? La correspondance de modèle peut fournir une meilleure solution, mais cela dépend vraiment de ce que vous essayez d'accomplir. –

Répondre

16

Le Value("User") dans votre Enumeration est de type Val. Et je crois que la mise en œuvre de equals ne compare pas le nom de la chaîne de la valeur. Je pense qu'une façon de faire cela est de créer votre propre Enumeration et Val afin qu'il retourne vrai si le nom correspond.

Mais dans mes usages de code, pas avec JPA, je convertis toujours la chaîne en MyEnumeration.Value. C'est facile avec des choses comme:

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

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

Notez que lors de l'utilisation withName, si la chaîne ne correspond à aucun nom dans l'énumération vous obtenez une exception.

Ensuite, toujours utiliser les champs d'énumération dans vos comparaisons:

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

Si JPA retourne seulement une chaîne, et il n'y a pas moyen de contourner cela. Ensuite, je pense que la meilleure option est soit de convertir la valeur en chaîne et de faire correspondre la chaîne à la chaîne, ou mettre à jour la chaîne à un Val et comparer Val. Le mélange de ces types ne fonctionnera pas à des fins de comparaison, sauf si vous implémentez une sorte d'extension à la méthode equals, et c'est compliqué.

13

L'expansion sur la réponse de Thomas, si vous utilisez la comparaison à la branche, en utilisant la correspondance de motif peut être plus approprié:

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

Vous pouvez alors l'utiliser comme suit:

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

ou

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