我正在尝试编写一个提取类型信息的宏。这是一个最小化的版本。
class Extractor[E] {
def extract(entity: E): Unit = macro ExtractorImpl.extractImpl[E]
}
object ExtractorImpl {
def extractImpl[E: c.WeakTypeTag](c: Context)(entity: c.Expr[E]): c.Tree = {
import c.universe._
val actualType = implicitly[WeakTypeTag[E]].tpe
c.info(c.enclosingPosition, actualType.toString, true)
q"{}"
}
}
以下是Extractor
的典型实现:
case class Person(name: String)
object PersonExtractor extends Extractor[Person]
如果我在PersonExtractor.extract(new Person("test name"))
中直接使用此类,则会将Person
打印为信息。但是,如果我间接使用它,如下所示,它只打印E
:
class Mapper[E](extractor: Extractor[E]) {
def extract(e: E) = extractor.extract(e)
}
class PersonMapper extends Mapper[Person](new Extractor[Person])
class Test {
new PersonMapper().extract(new Person("test name"))
}
如何将Person
类型设为actualType
?
答案 0 :(得分:1)
使用隐式宏
trait Extractor[E] {
def extract(entity: E): Unit
}
object Extractor {
implicit def i[E] : Extractor[E] = macro ExtractorImpl.extractImpl[E]
}
object ExtractorImpl {
def extractImpl[E: c.WeakTypeTag](c: Context):c.Tree = {
import c.universe._
val actualType = c.weakTypeOf[E]
c.info(c.enclosingPosition, actualType.toString, false)
q"""
new Extractor[$actualType]{
def extract(entity: $actualType): Unit = println("hello world")
}
"""
}
}
// test
case class Person(name: String)
//object PersonExtractor extends Extractor[Person]
class Mapper[E] {
def extract(e: E)(implicit extractor: Extractor[E]) = extractor.extract(e)
}
class PersonMapper extends Mapper[Person]
class Test {
new PersonMapper().extract(new Person("test name")) // show info:Person
}
编辑: // test2
class Mapper2[E](extractor: Extractor[E]) {
def extract(e: E) = extractor.extract(e)
}
object Mapper2 extends Mapper2[Person](Extractor.i[Person])//also show info:Person