Скала перечисления и отражения - PullRequest
3 голосов
/ 31 июля 2009

После долгой работы на Java я начал интересоваться Scala. В качестве учебного проекта я пытаюсь продублировать библиотеку Java, которая хранит и извлекает объекты состояния из базы данных. Для этого я хотел бы иметь возможность просто указать объект состояния следующим образом:

@PersistName("PERSON") case class  Person extends Entity {
  @Persist var id:Long = -1
  @Persist @MaxLength(80) var firstName = ""
  @Persist @MaxLength(80) var lastName = ""
  @Persist var gender = Gender.Male
  @Persist @MaxLength(80) var userName  = ""
  @Persist @OptionClass(classOf[Date]) var birthDay:Option[Date] = None
}

Код для сериализации / несериализации экземпляра Person использует отражение, чтобы знать типы полей и работает нормально для всех, кроме поля пола. Поле пола является перечислением, которое определяется как:

object Gender extends Enumeration {
  type Gender = Value
  val Male,Female,Unknown = Value
}

Проблема в том, что я не знаю, как я могу использовать отражение, чтобы создать новое значение Gender, используя только класс Person.

Ответы [ 4 ]

4 голосов
/ 31 июля 2009

Перечисление Scala интересно, но классы падежей часто имеют преимущество над ним:

sealed class Gender
case object Male extends Gender
case object Female extends Gender

Преимущество в том, что вы способны на match, и Scala даже будет жаловаться, если вы проверяете один пол, но не другой. И, кажется, облегчает вашу проблему. : -)

0 голосов
/ 11 мая 2016

Проверьте мой EnumReflector :

Вам необходимо указать тип поля scala.

val enumObject:Type = ... object's scala.Enumeration field
val typ:Type = ... object's scala.Enumeration field's scala type

val isEnum = EnumReflector.isEnumeration(typ)

val reflector = EnumReflector(typ)
val eid = reflector.toID(enumObject)
val enum = reflector.fromID(eid)
assertTrue(eid eq enum)

В проекте есть модульный тест, демонстрирующий это.

Также, смотрите мою развернутую версию этого ответа здесь: Можно ли использовать отражение, чтобы найти фактический тип поля, объявленного подтипом перечисления Scala?

0 голосов
/ 21 июля 2012

Я столкнулся с той же проблемой и нашел довольно громоздкое решение, но оно работает. Вам необходимо сохранить имя включающего перечисления, так как невозможно найти реальное перечисление из значения с помощью отражения.

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

val day = WeekDay.Fri

val className = day.getClass.getField("$outer").get(day).getClass.getCanonicalName

// write to database
// className // String
// day.id  // Int

Теперь, когда вы читаете из базы данных

// read from database
// obtain className and id

// enumObject will be WeekDay
val enumObject = Class.forName(className).getField("MODULE$").get().asInstanceOf[Enumeration]

// value will be WeekDay.Fri
val value = enumObject(id)
0 голосов
/ 03 августа 2009

Вы можете использовать Gender.Male.id, чтобы получить Int представление мужского пола. Используйте Gender.apply (), чтобы вернуть его:

val person = Person()

println("gender = " + person.gender.id)
// prints "gender = 0" on my mac

person.gender = Gender(Gender.Female.id) // have a little operation
println("gender = " + person.gender.id)
// prints "gender = 1" on my mac

Поскольку вы обрабатываете бит персистентности, все, что вам нужно сделать, это сохранить Int представление пола при сериализации и восстановить его обратно в Gender при десериализации.

Используйте пользовательскую аннотацию для полей перечисления, если вы хотите обобщить решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...