如何在运行时在 Scala 中查找类参数数据类型 [英] How to find class parameter datatype at runtime in scala

查看:38
本文介绍了如何在运行时在 Scala 中查找类参数数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._

def getType[T: TypeTag](obj: T) = typeOf[T]

case class Thing(
  val id: Int,
  var name: String
)
val thing = Thing(1, "Apple")

val dataType = getType(thing).decl(TermName("id")).asTerm.typeSignature

dataType match {
 case t if t =:= typeOf[Int] => println("I am Int")
 case t if t =:= typeOf[String] => println("String, Do some stuff")
 case _ => println("Absurd")
}

无法理解为什么结果是Absurd 而不是I am int?

Not able to digest why result is Absurd instead of I am int?

我的目标是在运行时知道类参数的数据类型并将其匹配到预定义的类型.

My aim is to know data-type of class parameter at runtime and match it to predefined types.

推荐答案

当前 dataTypetypeOf[Int] 都打印为 Int但是如果你做 showRaw 你就会明白为什么它们不匹配

Both current dataType and typeOf[Int] are printed as Int but if you do showRaw you'll see why they don't match

showRaw(dataType) // NullaryMethodType(TypeRef(ThisType(scala), scala.Int, List()))
showRaw(typeOf[Int]) // TypeRef(ThisType(scala), scala.Int, List())

问题是类型Int和返回Int的空方法的类型是不同的类型.

The thing is that just the type Int and the type of nullary method returning Int are different types.

尝试添加.resultType

val dataType = getType(thing).decl(TermName("id")).asTerm.typeSignature.resultType

dataType match {
  case t if t =:= typeOf[Int] => println("I am Int")
  case t if t =:= typeOf[String] => println("String, Do some stuff")
  case _ => println("Absurd")
} // I am Int


还值得一提的是,.decl(TermName("id")) 返回的是 getter 符号,它是 .decl(TermName("id"))(带有空格)返回字段符号.因此,或者您可以在符号名称中使用空格而不使用 .resultType


It's also worth mentioning that .decl(TermName("id")) returns getter symbol, it's .decl(TermName("id ")) (with a blank space) that returns field symbol. So alternatively you can do with a blank space in the symbol name and without .resultType

val dataType = getType(thing).decl(TermName("id ")).asTerm.typeSignature


我会在 @TomerShetah答案中补充,如果目标是";模式匹配"案例类的所有字段然后这也可以在编译时(主要是)使用 Shapeless 完成:


I'll add to @TomerShetah's answer that if the goal is "pattern matching" all fields of a case class then this can be done also at compile time (mostly) with Shapeless:

import shapeless.Poly1
import shapeless.syntax.std.product._

object printTypes extends Poly1 {
  implicit val int: Case.Aux[Int, Unit] = at(t => println(s"I am Int: $t"))
  implicit val string: Case.Aux[String, Unit] = at(t => println(s"String, Do some stuff: $t"))
  implicit def default[V]: Case.Aux[V, Unit] = at(t => println(s"Absurd: $t"))
}
  
thing.toHList.map(printTypes)
// I am Int: 1
// String, Do some stuff: Apple

https://scastie.scala-lang.org/DmytroMitin/N4Idk4KcRumQJZE2CHC0y

https://scastie.scala-lang.org/DmytroMitin/N4Idk4KcRumQJZE2CHC0yQ

这篇关于如何在运行时在 Scala 中查找类参数数据类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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