使用def宏实现抽象方法

0__*_*0__ 5 macros abstract-class scala

似乎不可能通过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
}
Run Code Online (Sandbox Code Playgroud)

此操作失败,并显示以下错误:

[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]       ^
Run Code Online (Sandbox Code Playgroud)

如果我删除extends A它编译.但显然我想AImpl满足特质A.如何解决这个问题?


另一个尝试:

trait AImpl extends A {
  def foo(): Unit = bar()
  def bar(): Unit = macro AImpl.fooImpl
}
Run Code Online (Sandbox Code Playgroud)

给出了新的错误:

[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
Run Code Online (Sandbox Code Playgroud)

gou*_*ama 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
Run Code Online (Sandbox Code Playgroud)