Материализация реализации в пакете - PullRequest
0 голосов
/ 12 мая 2018

При использовании макроса для реализации реализации свойства я хотел бы создать реализацию в пакете, чтобы он имел доступ к другим закрытым для пакета классам.

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] {} в рамках определенной упаковки?

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Как отметил Алексей Романов, это невозможно напрямую. Тем не менее, если вы вызываете только несколько методов (и если вы используете макрос, скорее всего, это так), одним из возможных (но не совершенных) обходных путей может быть создание открытого абстрактного класса или свойства, которое расширяет целевую характеристику и «публикует» все необходимые приватные методы пакета как protected прокси. Таким образом, вы можете создавать экземпляры в вашем макросе от наследования от этого абстрактного класса, а не от признака. Очевидно, что этот трюк эффективно «пропускает» эти методы кому угодно, но благодаря рефлексии любой может вызвать любой метод, если он действительно этого захочет. И злоупотребление этим трюком покажет столь же намеренное усилие обойти ваше разделение, как и использование отражения.

0 голосов
/ 22 мая 2018

Макрос должен расшириться до AST, который будет компилироваться в том месте, где находится вызов макроса. Поскольку package объявления разрешены только на верхнем уровне , а вызовы методов там запрещенырасширенное дерево не может ничего создать в другом пакете.

...