通过宏

时间:2016-11-30 00:23:07

标签: scala generics macros

我有一个简单的子类型关系,我已按如下方式设置:

trait Foo[T] {
    def a: Int
    def b: String
    def c: T
}

object Bar extends Foo[C] { /* implementation */ }
object Quux extends Foo[D] { /* implementation */ }
// ...

其中CD是具体类型。我还有一个管理器对象,它注册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的超类型列表了,但是我还没有弄清楚如何获取的类型参数对象声明,即我在这里寻找Uobject ... 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),关于如何执行此操作。

0 个答案:

没有答案