似乎无法通过def宏实现抽象方法:
import scala.reflect.macros.Context
import language.experimental.macros
trait A {
def foo(): Unit
}
object AImpl {
def fooImpl(c: Context)(): c.Expr[Unit] = {
import c.universe._
c.Expr[Unit](reify().tree)
}
}
trait AImpl extends A {
def foo(): Unit = macro AImpl.fooImpl
}
此操作失败,并显示以下错误:
[error] .../A.scala:17: overriding method foo in trait A of type ()Unit;
[error] macro method foo cannot override an abstract method
[error] def foo(): Unit = macro AImpl.fooImpl
[error] ^
如果我删除它编译的extends A
。但显然我希望AImpl
满足特质A
。如何解决这个问题?
另一次尝试:
trait AImpl extends A {
def foo(): Unit = bar()
def bar(): Unit = macro AImpl.fooImpl
}
给出了新的错误:
[error] macro implementation not found: bar (the most common reason for that is that
you cannot use macro implementations in the same compilation run that defines them)
[error] one error found
答案 0 :(得分:4)
您确定使用先编译的宏和稍后AImpl
进行测试吗?
像第二次尝试一样使用转发器方法似乎有效(使用2.10.2):
// first compilation run
import scala.reflect.macros.Context
import language.experimental.macros
trait A {
def foo(): Unit
}
object AImplMacros {
def fooImpl(c: Context)(): c.Expr[Unit] = {
import c.universe._
c.Expr[Unit](reify().tree)
}
}
// second compilation run
trait AImpl extends A {
def foo(): Unit = bar()
def bar(): Unit = macro AImplMacros.fooImpl
}
// compiles and runs:
scala> val a = new AnyRef with AImpl
a: AImpl = $anon$1@59225446
scala> a.foo
scala> a.bar
答案 1 :(得分:4)
我不确定这是否正确,所以请另外加一个权威的答案。
我才刚刚开始了解def宏是如何工作的。问题中的错误假设是def bar(): Unit = macro ...
实际上创建了一个运行时bar
方法。相反,它会创建......好吧,一个宏,所以对该宏的任何调用只会拼接在表达式中。
所以我看到了两件事。返回类型变为c.Expr[DefDef]
,但我不确定是否可能,并且可能还有更多工作要做。第二种选择是生成整个特征,例如,作为一个匿名类:
import scala.reflect.macros.Context
import language.experimental.macros
trait A {
def foo(): Unit
}
object AImpl {
def body: A = macro bodyImpl
def bodyImpl(c: Context): c.Expr[A] = {
import c.universe._
val r = reify { new A { def foo() { println("schoko" )}}}
c.Expr[A](r.tree)
}
}
然后代替mixin,你有组合:
object AHolder extends App {
val bar: A = AImpl.body
bar.foo()
}
最糟糕的是,我需要使用sbt设置子项目,否则这些文件不能同时编译: - /