我想获得一个类型的名称,作为String,没有运行时反射。
使用宏,并使用该类型的实例,我可以这样做:
def typeNameFromInstance[A](instance: A): String =
macro typeNameFromInstanceImplementation[A]
def typeNameFromInstanceImplementation[A](
c: Context)(
instance: c.Expr[A]): c.Expr[String] = {
import c.universe._
val name = instance.actualType.toString
c.Expr[String](Literal(Constant(name)))
}
如果没有该类型的实例,我怎么能这样做?我想要一个像:
这样的函数签名def typeName[A]: String
我不能使用ClassTags,因为它们不提供完整的类型名称,只提供已擦除的类型。由于thread safety issues,我显然也无法使用TypeTags。
编辑:看起来这是不可能的完全通用性(例如嵌套函数调用)。下面接受的答案在评论中说明了这一点。
答案 0 :(得分:1)
您可以访问代表宏应用程序的树:c.macroApplication
def typeName[T]: String = macro typeName_impl[T]
def typeName_impl[T](c: Context): c.Expr[String] = {
import c.universe._
val TypeApply(_, List(typeTree)) = c.macroApplication
c.literal(typeTree.toString())
}
修改强>
获得相同的另一种方式,但可能更好一点:
def typeName[T]: String = macro typeName_impl[T]
def typeName_impl[T: c.WeakTypeTag](c: Context): c.Expr[String] = {
import c.universe._
c.literal(weakTypeOf[T].toString())
}