在包内实现实现

Materialize implementation within package

当使用宏实现特征的实现时,我想在包内创建实现,以便它可以访问其他包私有 类。

trait MyTrait[T]

object MyTrait {
  implicit def materialize[T]: MyTrait[T] = macro materializeImpl[T]

  def materializeImpl[T : c.WeakTypeTag](c: blackbox.Context): c.Expr[MyTrait[T]] = {
    val tt = weakTypeTag[T]
    c.Expr[MyTrait[T]](q"new MyTrait[$tt] {}")
  }
}

是否可以在特定包中实现 new MyTrait[$tt] {}

一个宏必须扩展成一个 AST,它会在宏调用所在的地方编译。由于 package 声明 are only allowed at top-level,并且那里不允许方法调用,扩展树无法在另一个包中创建任何东西。

正如 Alexey Romanov 指出的那样,这是不可能直接实现的。尽管如此,如果您只调用几个方法(如果您使用宏,很可能就是这样),一种可能(但不完美)的解决方法可能是创建一个 public 抽象 class 或扩展目标特征和 "publishes" 所有必需的包私有方法作为 protected 代理。因此,您可以通过继承抽象 class 而不是特征来在宏中创建实例。显然,这个技巧对任何人都有效 "leaks" 这些方法,但由于反射,任何人都可以调用任何方法,如果他真的想要的话。滥用此技巧将显示为故意绕过您的分离,就像使用反射一样。