scala: использование метода расширения класса на основе макросов вызывает черту по умолчанию impl, если тип экземпляра статически является базовым классом

У меня есть черта T, я реализую его с помощью макроса в классе C. Я создаю экземпляр C и вызываю его методы. если типом val, содержащим экземпляр C, является C - работает как ожидалось. если типом val, содержащим экземпляр C, является T - вызывает методы, как если бы T.

лучший способ описать это, что я могу придумать, это «разбить виртуальную таблицу» в макросах scala, но я не знаю, так ли это ...

пример кода:

Type in expressions for evaluation. Or try :help.

scala>

scala>

scala> import language.experimental.macros
import language.experimental.macros

scala>

scala>

scala> trait T { def doSomething(): Unit = println ("trait") }
defined trait T

scala>

scala>

scala> import scala.reflect.macros.Context
import scala.reflect.macros.Context

scala>

scala>

scala> object Macro {
     |   def doSomething(c: Context)(): c.universe.Tree = {
     |     import c.universe._
     |     q"""println ("macro")"""
     |   }
     | }
warning: there was one deprecation warning (since 2.11.0); for details, enable `:setting -deprecation' or `:replay -deprecation'
defined object Macro

scala>

scala>

scala> class C extends T { override def doSomething(): Unit = macro Macro.doSomething }
defined class C

scala>

scala> val c: C = new C()
c: C = C@3bd1883a

scala> c.doSomething()
macro

scala>

scala> val t: T = new C()
t: T = C@4079fec7

scala> t.doSomething()
trait

Всего 1 ответ


Макросы Def раскрываются во время компиляции, поэтому для них невозможна поздняя привязка / динамическая диспетчеризация (которая является функцией времени выполнения).

Во время компиляции неизвестно, что t имеет тип C , во время компиляции известно только, что t имеет тип T

Подробности смотрите здесь: Евгений Бурмако. Объединение метапрограммирования времени компиляции и времени выполнения в Scala https://infoscience.epfl.ch/record/226166/files/EPFL_TH7159.pdf с. 98, §4.6.1 «Наследование»


Есть идеи?

10000