假设我们有一个东西的模型,表示为case class
,如此
case class User(firstName:String,lastName:String,age:Int,planet:Option[Planet])
sealed abstract class Planet
case object Earth extends Planet
case object Mars extends Planet
case object Venus extends Planet
基本上,通过使用反射或宏,可以获取用户案例类的字段名称,以及字段所代表的类型。这还包括Option
,即在提供的示例中,需要能够区分Option[Planet]
和Planet
在scala' ish伪代码中,类似这样的
val someMap = createTypedMap[User] // Assume createTypedMap is some function which returns map of Strings to Types
someMap.foreach{case(fieldName,someType) {
val statement = someType match {
case String => s"$fieldName happened to be a string"
case Int => s"$fieldName happened to be an integer"
case Planet => s"$fieldName happened to be a planet"
case Option[Planet] => s"$fieldName happened to be an optional planet"
case _ => s"unknown type for $fieldName"
}
println(statement)
}
我目前知道您无法执行case Option[Planet]
之类的内容,因为它会被Scala的删除删除,但即使使用TypeTags
,我也无法写代码执行我想做的事情,并可能处理其他类型(如Either[SomeError,String]
)。
目前我们使用的是最新版本的Scala(2.11.2),因此任何使用TypeTags
或ClassTags
或宏的解决方案都绰绰有余。
答案 0 :(得分:1)
选项是类型参数化类型(选项[T])。在运行时,除非您已将代码结构化以使用type tags,否则由于类型擦除,您无需区分Option [String]和Option [Int](对于所有类型参数化类型都是如此) )。 尽管如此,您可以区分选项[*]和行星。请记住第一期。
通过反思,在课堂上获取所有“事物”很容易。例如,假设您只想要getter(您可以放置其他类型的过滤器,其中有很多过滤器,并且当继承是过程的一部分时,并非所有过滤器都按预期运行,因此您需要进行一些实验):
import reflect.runtime.{universe=>ru}
val fieldSymbols = ru.typeOf[User].members.collect{
case m: ru.MethodSymbol if m.isGetter => m
}
如果您在实例而不是类上调用代码,那么您将拥有的另一个选项是遍历每个方法,调用方法并将结果分配给变量,然后测试变量的类型。这假设您只调用不会改变实例状态的方法。
您有很多选择,有时间找到最适合您需求的产品。
答案 1 :(得分:-1)
这是一个很长的镜头,但也许Shapeless可以帮助你。