我正在为一个问题而挣扎,我不知道如何解决它。我希望更有经验的Scala程序员能给我一个启示!
我有以下宏:
object Model {
trait Model[T <: Product] {
def showAttrs(): Unit
}
def getModel[T <: Product]: Model[T] = macro getModelImpl
}
宏的目的是返回一个Model实例,该实例显示T的属性(如果T是事例类)!
我希望能够做到以下几点:
def f[T <: Product](implicit m: Model[T]): Unit = {
m.showAttrs()
}
case class Number(n: Int)
f[Number]()
当我们执行以下操作时,其原理与标量反射相同:
case class Number(n: Int)
def getInfo[T](implicit tag: TypeTag[T]): Unit = println(tag)
看到了吗?!我们得到一个Type:)(GREAT!)的实例。
怎么做这样的事?scala反射包是否提供了一些隐含在幕后的具体内容?如果是这样的话,我怎样才能达到同样的结果呢?
您的MyTypeTag[T]
应该完成什么?
如果您的特性在T
上是不变的,并且根本没有任何类型相关的逻辑,那么最简单的解决方案可以是定义方法
implicit def arbMyTypeTag[T] = new MyTypeTag { ... }
更复杂的变体取决于其他已解决的隐含词
implicit def optionMonoid[T: Semigroup] = new Monoid[Option[T]] { ... }
更复杂的变体依赖于相同类型的
implicit def tupleMonoid[A,B](implicit ma: Monoid[A], mb: Monoid[B]) = new Monoid[(A,B)]{...}
编译器能够解析这样的递归隐式。
最核心的方法是通过隐式宏使用类型和表达式的整个编译时信息,这最接近于TypeTag
分辨率,这可能会导致非常复杂的错误