2010-08-04 10 views
10

Tengo una enumeración en scala asignada a cadenas en JPA. Para una codificación más cómoda, definí las conversiones implícitas entre ellos. Así que ahora puedo definir el valor val person.role = "User", - person.role es el tipo de enumeración una cadena así que está la conversión. Pero cuando trato de comparar estos dos, siempre obtengo el falso, porque el def equals (arg0: Any) : Boolean toma Any para que no haya ninguna conversión activada. Necesito alguna conversión explícita, pero mi plan era poder omitir eso, ¿cuál cree que es la mejor práctica? la mejor solución aquí?Comparación de cadenas y enumeraciones

+0

¿Está basando este mapeo en 'Enumeración' y 'Valor'? – Thomas

+0

@Thomas sí Estoy usando scala's 'scala.Enumeration' y' scala.Enumeration.Value' – coubeatczech

+0

¿Cuál es el contexto/caso de uso para la comparación? La coincidencia de patrones puede proporcionar una mejor solución, pero realmente depende de lo que está tratando de lograr. –

Respuesta

16

El Value("User") en su Enumeration es del tipo Val. Y creo que su implementación de equals no compara el nombre de la cadena del valor. Creo que una manera dura de hacer esto es crear tu propio Enumeration y Val para que devuelva verdadero si el nombre coincide.

Pero en mi código utiliza, no con JPA, siempre convierto la cadena en MyEnumeration.Value. Esto es fácil con cosas como:

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

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

Tenga en cuenta que cuando se utiliza withName, si la cadena no coincide con cualquier nombre en la enumeración se obtiene una excepción.

utilice siempre los campos de enumeración en sus comparaciones:

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

Si APP sólo se devuelve una cadena, y no hay manera de evitarlo. Entonces creo que la mejor opción es convertir el valor a cadena y hacer coincidir cadena con cadena, o actualizar la cadena a Val y comparar Val. Mezclar estos tipos no funcionará para comparar, a menos que implemente algún tipo de extensión al método equals, y eso es complicado.

13

Ampliando la respuesta de Thomas, si está utilizando la comparación en rama, el uso de la coincidencia de patrones puede ser más apropiado:

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

A continuación, puede utilizar esto como sigue:

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 
    ... 
} 
Cuestiones relacionadas