动态混合特征 [英] Mixing in a trait dynamically
问题描述
具有特征
trait Persisted {
def id: Long
}
我如何实现一个接受任何case类的实例并返回其特征混合在一起的副本的方法?
how do I implement a method that accepts an instance of any case class and returns its copy with the trait mixed in?
方法的签名如下:
def toPersisted[T](instance: T, id: Long): T with Persisted
推荐答案
这可以通过宏(自2.10.0-M3以来正式成为Scala的一部分)来完成. 这是您要查找的内容的主要示例.
This can be done with macros (that are officially a part of Scala since 2.10.0-M3). Here's a gist example of what you are looking for.
1)我的宏生成一个本地类,该类继承自提供的case类并被持久化,就像new T with Persisted
一样.然后,它会缓存其参数(以防止进行多次评估)并创建所创建类的实例.
1) My macro generates a local class that inherits from the provided case class and Persisted, much like new T with Persisted
would do. Then it caches its argument (to prevent multiple evaluations) and creates an instance of the created class.
2)我怎么知道要生成什么树?我有一个简单的应用程序parse.exe,该应用程序打印由解析输入代码产生的AST.因此,我只调用了parse class Person$Persisted1(first: String, last: String) extends Person(first, last) with Persisted
,记下了输出并在宏中复制了它. parse.exe是scalac -Xprint:parser -Yshow-trees -Ystop-after:parser
的包装.有多种探索AST的方法,请参见在Scala 2.10中进行元编程" .
2) How did I know what trees to generate? I have a simple app, parse.exe that prints the AST that results from parsing input code. So I just invoked parse class Person$Persisted1(first: String, last: String) extends Person(first, last) with Persisted
, noted the output and reproduced it in my macro. parse.exe is a wrapper for scalac -Xprint:parser -Yshow-trees -Ystop-after:parser
. There are different ways to explore ASTs, read more in "Metaprogramming in Scala 2.10".
3)如果您提供-Ymacro-debug-lite
作为scalac的参数,则可以检查宏扩展.在这种情况下,所有扩展都将被打印出来,您将能够更快地检测到代码生成错误.
3) Macro expansions can be sanity-checked if you provide -Ymacro-debug-lite
as an argument to scalac. In that case all expansions will be printed out, and you'll be able to detect codegen errors faster.
编辑.更新了2.10.0-M7的示例
edit. Updated the example for 2.10.0-M7
这篇关于动态混合特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!