2009-07-31 2 views
3

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

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

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

+0

Почему «используя только класс Person»? – Blaisorblade

ответ

4

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

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

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

0

Вы можете использовать Gender.Male.id, чтобы получить представление о мужской ценности для мужчин. Используйте 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 гендера при сериализации и восстановить его обратно Пол при десериализации.

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

0

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

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

Проверьте мой 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) 

В проекте есть единичный тест, который демонстрирует его.

Кроме того, см мой расширить версию этого ответа здесь: Is it possible to use reflection to find the actual type of a field declared to be a Scala Enumeration subtype?