Warm tip: This article is reproduced from serverfault.com, please click

reflection-如何在Scala中的运行时查找类参数数据类型

(reflection - How to find class parameter datatype at runtime in scala)

发布于 2020-11-29 16:12:51
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

我的目的是在运行时了解类参数的数据类型,并将其与预定义类型匹配。

Questioner
Raj Kishor
Viewed
0
Dmytro Mitin 2020-12-02 12:15:16

当前dataTypetypeOf[Int]都打印为,Int但是如果你这样做showRaw,将会看到为什么它们不匹配的原因

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

事实是,Int返回的空方法的类型和类型Int是不同的类型。

尝试添加 .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

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

我将添加到@TomerShetah答案中,如果目标是“模式匹配” case类的所有字段,那么也可以在编译时(主要是使用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/N4Idk4KcRumQJZE2CHC0yQ