假设我有几种方法的特征 Foo
. 我想创建一个新的特性,扩展 Foo
但每个方法调用"wraps",例如使用一些print语句(实际上这将是更复杂的东西/我有几个不同的用例) .
trait Foo {
def bar(x: Int) = 2 * x
def baz(y: Int) = 3 * y
}
我可以通过覆盖每个方法手动完成此操作 . 但这似乎不必要地冗长(并且很容易调用错误的超级方法):
object FooWrapped extends FooWrapped
trait FooWrapped extends Foo {
override def bar(x: Int) ={
println("call")
super.bar(x)
}
override def baz(y: Int) ={
println("call")
super.baz(y)
}
}
scala> FooWrapped.bar(3)
call
res3: Int = 6
我希望写一个mixin特性,我可以重用其他特征,并用作:
trait FooWrapped extends Foo with PrintCall
这样我就不必手动覆盖每个方法(mixin会为我做这个) .
是否有可能在Scala中编写这样的mixin特性?它会是什么样子?
1 回答
Update 这是宏 . 由于quasiquotes,它比我想象的要痛苦得多 . 他们真棒 . 这段代码只做了一点,你可能需要改进它 . 它可能无法解释某些特殊情况 . 此外,它假设既没有父类也没有父母方法,如果你有辅助构造函数等它可能不起作用 . 我仍然希望它会让你知道如何为你的特定需求做到这一点,使它适用于所有的不幸的是,这种情况对我来说太大了 .
如果您不想创建实例,但是您确实只想为您的特征添加日志记录以便进一步混合,则可以使用相对相同的代码执行此操作,但使用宏天堂类型注释:http://docs.scala-lang.org/overviews/macros/annotations这些允许您标记您的类定义并在定义内执行修改
你可以用
Dynamic
做你想做的事情,但是有一个问题 - 你可以't make it of original type, so it'不是混合 . 动态仅在类型检查失败时才开始工作,因此您可以稍后再提出它 . 如果你不在这里寻找DI,那么Dynamic
可能对你有用你可以在这里阅读更多关于
Dynamic
的内容:https://github.com/scala/scala/blob/2.12.x/src/library/scala/Dynamic.scala