Scala获取案例类的字段和字段类型 [英] Scala getting field and type of field of a case class

查看:933
本文介绍了Scala获取案例类的字段和字段类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我试图在案例类中获取字段及其类型.此刻我正在这样做

So I'm trying to get the field and their types in a case class. At the moment I am doing it like so

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

问题是x.typeSignature的类型为reflect.runtime.universe.Type,不能与case类中驻留的任何类型匹配.有什么方法可以做到这一点?

the problem is x.typeSignature is of type reflect.runtime.universe.Type which cannot match on any of the types that reside in the case class. Is there some way to do this?

推荐答案

假设您定义了以下案例类:

Let's say you have the following case class defined:

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

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

with pattern matching you can achieve what you want with the following:

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")
}

为什么?

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

Why?

So why the first attempt does not work?

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

That's because in your code you are using type-patterns. Type patterns check the type of subject-to-match - which is a type signature in this case - at runtime. So by using _: Int we are asking for a type check at runtime against each type signature of non-method members of CaseClass.

但是在这种情况下,我们需要一个值匹配.

But in this case what we need is a value match.

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

Let's take a closer look (using 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只是这些类型的字符串表示形式,而不是其实际类型!

So what we want to match is of type reflect.runtime.universe.Type. Note that in the last line, String and scala.Int are just string representations of these types not their actual type!

因此,我们需要将它们与该类型的不同值进行匹配,这些值可以通过typeOf[Int]typeOf[String]轻松获得.

So we need to match them against different values of this type which we can easily get with typeOf[Int] and typeOf[String].

您可能想通过使用以下代码使代码更简洁:

You may want to make the code more concise by using the following code:

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

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

But this give you the following compile error:

not found: type typeOf

同样是因为在这里我们需要匹配以大写字母开头的变量名.因此,以下工作有效:

Again this is because here we need to match against a variable name beginning with an uppercase letter. So the following works:

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

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

有关模式匹配的更多详细信息,请参考在Scala中编程.您将在此处找到模式匹配的详细说明.

For more details on pattern matching, refer to Programming in Scala. You will find a detailed explanation of pattern matching there.

这篇关于Scala获取案例类的字段和字段类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆