Scala得到案件类的领域和类型

时间:2014-10-22 04:53:58

标签: scala reflection pattern-matching match case-class

所以我试图在案例类中获取字段及其类型。目前我正在这样做

typeOf[CaseClass].members.filter(!_.isMethod).foreach{
   x =>
     x.typeSignature match {
        case _:TypeOfFieldInCaseClass => do something
        case _:AnotherTypeOfFieldInCaseClass => do something
     }
}

问题是x.typeSignature的类型为reflect.runtime.universe.Type,它与案例类中的任何类型都不匹配。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:12)

我们假设您已定义以下案例类:

case class CaseClass(i: Int, s: String)

通过模式匹配,您可以通过以下方式实现您想要的目标:

import scala.reflect.runtime.universe._

typeOf[CaseClass].members.filter(!_.isMethod).map(_.typeSignature).foreach {
  case t if t == typeOf[Int] => print("i")
  case s if s == typeOf[String] => print("s")
}

为什么?

那么为什么第一次尝试不起作用?

那是因为在你的代码中你正在使用类型模式。类型模式在运行时检查主题匹配的类型 - 在这种情况下是类型签名。因此,通过使用_: Int,我们要求在运行时针对CaseClass的非方法成员的每个类型签名进行类型检查。

但在这种情况下,我们需要的是价值匹配。

让我们仔细看看(使用Scala REPL):

scala> case class CaseClass(i: Int, s: String)
defined class CaseClass

scala> typeOf[CaseClass]
res1: reflect.runtime.universe.Type = CaseClass

scala> typeOf[CaseClass].members
res2: reflect.runtime.universe.MemberScope = Scopes(method equals, method toString, ..)

scala> typeOf[CaseClass].members.filter(!_.isMethod)
res4: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(value s, value i)

scala> typeOf[CaseClass].members.filter(!_.isMethod).map(_.typeSignature)
res5: Iterable[reflect.runtime.universe.Type] = List(String, scala.Int)

所以我们要匹配的是reflect.runtime.universe.Type类型。请注意,在最后一行中,Stringscala.Int只是这些类型的字符串表示,而不是它们的实际类型!

因此,我们需要将它们与此类型的不同值相匹配,我们可以使用typeOf[Int]typeOf[String]轻松获取这些值。

关于Scala

中模式匹配的更多信息

您可能希望使用以下代码使代码更简洁:

typeOf[CaseClass].members.withFilter(!_.isMethod).map(_.typeSignature).foreach {
  case typeOf[Int] => print("i")    // Won't Compile!
  case typeOf[Int] => print("s")    // Won't Compile
}

但这会给你以下编译错误:

not found: type typeOf

这也是因为我们需要匹配以大写字母开头的变量名称。以下是有效的:

val T = typeOf[Int]
val S = typeOf[String]

typeOf[CaseClass].members.withFilter(!_.isMethod).map(_.typeSignature).foreach {
  case T => print("i")
  case S => print("s")
}

有关模式匹配的更多详细信息,请参阅Programming in Scala。你会在那里找到模式匹配的详细解释。