所以我试图在案例类中获取字段及其类型。目前我正在这样做
typeOf[CaseClass].members.filter(!_.isMethod).foreach{
x =>
x.typeSignature match {
case _:TypeOfFieldInCaseClass => do something
case _:AnotherTypeOfFieldInCaseClass => do something
}
}
问题是x.typeSignature
的类型为reflect.runtime.universe.Type
,它与案例类中的任何类型都不匹配。有没有办法做到这一点?
答案 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
类型。请注意,在最后一行中,String
和scala.Int
只是这些类型的字符串表示,而不是它们的实际类型!
因此,我们需要将它们与此类型的不同值相匹配,我们可以使用typeOf[Int]
和typeOf[String]
轻松获取这些值。
您可能希望使用以下代码使代码更简洁:
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。你会在那里找到模式匹配的详细解释。