4

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

问题是我不知道如何使用反射也只使用 Person 类创建一个新的 Gender 值。

4

4 回答 4

4

Scala 的 Enumeration 很有趣,但案例类通常比它更有优势:

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

这有一个优势,match如果你测试一种性别而不是另一种性别,Scala 甚至会抱怨。而且,它似乎更容易解决您的问题。:-)

于 2009-07-31T16:34:13.930 回答
0

您可以使用 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。

如果要概括解决方案,请在枚举字段上使用自定义注释。

于 2009-08-03T09:45:38.383 回答
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)
于 2012-07-20T21:22:07.757 回答
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)

项目中有一个单元测试来演示它。

另外,请在此处查看此答案的扩展版本:是否可以使用反射来查找声明为 Scala Enumeration 子类型的字段的实际类型?

于 2016-05-11T15:57:39.547 回答