在定义宏实现时尝试通过WeakTypeTag引用获取类的名称时,如果应用了多层多态性,我似乎无法获得正确的信息。
例如,如果我具有以下设置:
object MacroSupport {
def get_name_impl[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[String] = {
val nameOfA: String = weakTypeOf[A].toString
...
}
def getName[A] = macro get_name_impl[A]
}
abstract class GenericInterface[T] {
def getName: String = MacroSupport.getName[T]
}
case class ContainerA(
someValue: String
)
class FunctionalClass extends GenericInterface[ContainerA] {
val containerName: String = getName
}
我希望实现的是拥有任意数量的FunctionalClass
,每个都有自己的Container
类,并且他们可以报告其容器的名称,该名称用于某些元配置。基本上MacroSupport
和GenericInterface
将存在于我正在编写的库中,而FunctionalClass
和Container
级别将由使用该库的其他人编写。
由于GenericInterface
,FunctionalClass.containerName
==“ t”中的直通类型,我遇到的问题以及尝试访问Type声明均未产生任何问题。如何从FunctionalClass
声明到MacroSupport
级别获取类型信息?
答案 0 :(得分:1)
尝试实现类的实现
https://docs.scala-lang.org/overviews/macros/implicits.html#implicit-materializers
import scala.reflect.macros.blackbox
import scala.language.experimental.macros
object MacroSupport {
def getName[A](implicit gn: GetName[A]): String = gn()
trait GetName[A] {
def apply(): String
}
object GetName {
implicit def materializeGetName[A]: GetName[A] = macro materializeGetNameImpl[A]
def materializeGetNameImpl[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[GetName[A]] = {
import c.universe._
c.Expr[GetName[A]] {
q"""
new MacroSupport.GetName[${weakTypeOf[A]}] {
override def apply(): _root_.java.lang.String = ${weakTypeOf[A].toString}
}
"""
}
}
}
}
import MacroSupport.GetName
abstract class GenericInterface[T: GetName] {
def getName: String = MacroSupport.getName[T]
}
case class ContainerA(
someValue: String
)
class FunctionalClass extends GenericInterface[ContainerA] {
val containerName: String = getName
}
(new FunctionalClass).containerName // ContainerA
顺便说一下,shapeless.Typeable
完成了这项工作。 Typeable[A].describe
就像我们的MacroSupport.getName[A]
。