У меня есть перечисление в scala, сопоставленное строкам в JPA. Для более удобного кодирования я определял неявные преобразования между ними. Поэтому теперь я могу определить значение val person.role = "User"
, - person.role
- это тип перечисления "User"
a String, чтобы преобразование. Но когда я пытаюсь сравнить эти два, я всегда получаю false, потому что def equals (arg0: Any) : Boolean
занимает Any
, поэтому никакого преобразования не запускается. Мне нужно некоторое явное преобразование, но мой план состоял в том, чтобы упустить это, как вы думаете, это лучшая практика | здесь самое лучшее решение?
Сравнение строк и перечислений
Ответ 1
Value("User")
Value("User")
имеет тип Val
. И я считаю, что реализация equals
не сравнивает имя строки значения. Я думаю, что один тяжелый способ сделать это - создать свои собственные Enumeration
и Val
, чтобы он возвращал true, если имя соответствует.
Но в моем коде используется не JPA, я всегда конвертирую строку в MyEnumeration.Value
. Это легко с такими вещами, как:
object E extends Enumeration { val User = Value("User") }
scala> val a = E.withName("User")
a: E.Value = User
Обратите внимание, что при использовании withName
, если строка не соответствует ни одному имени в перечислении, вы получаете исключение.
Затем всегда используйте поля перечисления в своих сравнениях:
scala> a == E.User
res9: Boolean = true
Если JPA возвращает только строку, и ее нет. Тогда я думаю, что лучший вариант - либо преобразовать значение в строку и строку соответствия в строку, либо обновить строку до Val и сравнить Val. Смешивание этих типов не будет работать для сравнения, если вы не реализуете какое-то расширение для метода equals
, и это сложно.
Ответ 2
Развернувшись на ответ Томаса, если вы используете сравнение с веткой, использование шаблонов может быть более подходящим:
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)
}
}
Затем вы можете использовать это следующим образом:
def allowAccess(role: String): Boolean = role match {
case Role.Admin() => true
case Role.User() => false
case _ => throw ...
}
или
// str is a String
str match {
case Role(role) => // role is a Role.Value
case Realm(realm) => // realm is a Realm.Value
...
}