我有一个简单的子类型关系,我已按如下方式设置:
trait Foo[T] {
def a: Int
def b: String
def c: T
}
object Bar extends Foo[C] { /* implementation */ }
object Quux extends Foo[D] { /* implementation */ }
// ...
其中C
和D
是具体类型。我还有一个管理器对象,它注册Foo[T]
类型的对象,并且需要维护泛型类型信息才能正确调用方法c
。
scala编译器似乎无法在此处为我的经理register
方法正确推断类型,因此我需要手动指定。即,我无法做到
Manager register Bar
但必须提供
Manager register[C, Bar.type] Bar
为了使这更漂亮一点,我写了一个自动执行此操作的宏,但我仍然坚持检索对象继承的特征的具体类型参数。宏的基本形式如下:
def macro_impl[T: c.WeakTypeTag](c: whitebox.Context)(a: c.Expr[T]): c.Expr[Unit] = {
import c.universe._
val typeIWant = weakTypeOf[T].???
c.Expr[Unit](q"com.example.Manager.register[${a.actualType}, ${typeIWant}]($a)")
}
我已经能够检索T
的超类型列表了,但是我还没有弄清楚如何获取中的类型参数对象声明,即我在这里寻找U
:object ... extends Foo[U]
)。有没有办法做到这一点?
编辑:我可以通过反射获取我想要在控制台中显示的类型信息:
scala> typeOf[Bar].typeSymbol.info
res1: reflect.runtime.universe.Type =
com.example.Foo[com.example.C] {
def <init>(): com.example.Bar
def a: scala.Int
def b: String
def c(event: com.example.C): scala.Unit
}
但我仍然不确定如何获取有关签名com.example.Foo[com.example.C]
部分的信息。在反射API文档中没有找到任何相关内容(特别是TypeApi
),关于如何执行此操作。