scala:如果实例的类型静态地是基类,则使用基于宏扩展类的方法调用trait default impl

scala:如果实例的类型静态地是基类,则使用基于宏扩展类的方法调用trait default impl,scala,scala-macros,Scala,Scala Macros,我有一个特质T, 我用C类中的宏实现它。 我创建一个C实例并调用其方法。 如果包含C实例的val的类型为C,则按预期工作。 如果包含C实例的val的类型为T,则调用方法的方式与调用T的方式相同 我能想到的最好的描述方法是scala宏中的“虚拟表损坏”,但我不知道这是否是一件事 示例代码: 键入表达式以进行计算。或者尝试:帮助。 斯卡拉> 斯卡拉> scala>导入语言.experimental.macros 导入language.experimental.macros 斯卡拉> 斯卡拉> sca

我有一个特质T, 我用C类中的宏实现它。 我创建一个C实例并调用其方法。 如果包含C实例的val的类型为C,则按预期工作。 如果包含C实例的val的类型为T,则调用方法的方式与调用T的方式相同

我能想到的最好的描述方法是scala宏中的“虚拟表损坏”,但我不知道这是否是一件事

示例代码:

键入表达式以进行计算。或者尝试:帮助。
斯卡拉>
斯卡拉>
scala>导入语言.experimental.macros
导入language.experimental.macros
斯卡拉>
斯卡拉>
scala>trait T{def doSomething():Unit=println(“trait”)}
定义性状T
斯卡拉>
斯卡拉>
scala>导入scala.reflect.macros.Context
导入scala.reflect.macros.Context
斯卡拉>
斯卡拉>
scala>对象宏{
|def doSomething(c:Context)(:c.universe.Tree={
|导入c.universe_
|q“println(“宏”)”
|   }
| }
警告:有一个弃用警告(自2.11.0起);有关详细信息,请启用“:设置-弃用”或“:重播-弃用”
定义的对象宏
斯卡拉>
斯卡拉>
scala>C类扩展了T{override def doSomething():Unit=macro macro.doSomething}
定义的C类
斯卡拉>
scala>val c:c=new c()
c:c=C@3bd1883a
scala>c.剂量测定法()
宏
斯卡拉>
scala>valt:t=newc()
t:t=C@4079fec7
scala>t.doSomething()
特质

Def宏是在编译时展开的,因此它们不可能进行后期绑定/动态调度(这是一项运行时功能)

在编译时不知道
t
的类型是
C
,在编译时只知道
t
的类型是
t

详情如下: 尤金·伯马科。Scala中编译时和运行时元编程的统一
P98,§4.6.1“继承”

我的实际用例为scala日志记录提供了一个PR,我希望一个基本特征“ALogger”由两个不同的宏实现来实现,并且希望记录器的使用者能够抽象地说他们有ALogger,但记录器稍后将通过Mixin或继承来确定。也许这是一个遗憾的宏是幼稚的这种方式。也许这可以通过一个瘦生成的包装器特性在内部包装,该特性以正常的可预测方式运行,并且有一个扩展宏实现。我不知道这会有什么影响,但很有趣。@nathang抱歉,我不明白“瘦生成包装特性”(不管它是什么意思)有什么帮助。在运行时,
x中的
foo()
。foo()
是基于
x
的运行时类选择的。这个信息在编译时还不知道。您可以在编译时为运行时保存信息(类型标记、tasty、semanticdb)。但为了在编译时使用运行时信息,您需要时间机器。或者,您必须大量更改标准工作流:第一次编译时、第一次运行时(持久化信息)、第二次编译时(使用持久化信息)、第二次运行时。