我刚刚发现了如何使用duck typing来创建 Scala中的mixins动态扩展了它的行为 在不知道mixin的情况下创建的类。我能够做到这一点 创建一个mixin,添加一个装饰的方法'现有方法。这是 如下图所示。
trait Foobar {
this: {def origGreetingMethod()} => // this is 'duck typing' right?
def decoratedGreetingMethod() = {
origGreetingMethod() ; println("done greeting")
}
}
class Tarbar { def origGreetingMethod() = { println("hello") }}
val y = new Tarbar() with Foobar
y.decoratedGreetingMethod // when run from REPL prints "hello\ndone greeting"
请注意,装饰方法的名称与原始名称不同。我在想 : 有没有什么方法可以覆盖和扩展ORGINAL方法(即origGreetingMethod) 由mixin方法装饰的类?
这就是我想要这样做的原因:(1)说我有采用Tarbar实例的方法...... 并且(2)让我们说这个方法和它引用的Tarbar类是在没有的情况下开发的 我的要求是每次在Tarbar上调用origGreetingMethod之后我都需要做点什么 else(收集指标,清理......无论如何)。
def doSomething(tarbar: Tarbar) {
tarbar. origGreetingMethod
println("doing something useful...")
}
如果我可以调整Foobar以便覆盖其中的行为,那将是非常方便的 origGreetingMethod并不要求我调用decoratedGreetingMethod来获取它 新功能。
我尝试了这篇文章中提到的抽象覆盖方法: Mixins in Scala
但我无法让它发挥作用。任何指导最感谢! 感谢
答案 0 :(得分:1)
我开始玩一些代码。我想知道这是不是你的想法:
scala> class Tarbar { def origGreetingMethod() = println("hello") }
defined class Tarbar
scala> trait Foobar extends Tarbar {
| abstract override def origGreetingMethod() = {
| super.origGreetingMethod()
| println("extra") }}
defined trait Foobar
scala> val y = new Tarbar() with Foobar
y: Tarbar with Foobar = $anon$1@cbf6c1e
scala> y.origGreetingMethod()
hello
extra
我认为@SillyFreak提供了这个答案。我只是将它插入到您的示例代码中。
答案 1 :(得分:0)
此 的方式是使用abstract override def
。 this page有一个很好的例子,这是一个准系统的例子:
trait Trait {
def foo(): Unit
}
trait A extends Trait {
def foo(): Unit = println("A")
}
trait B extends Trait {
abstract override def foo(): Unit = { println("B"); super.foo() }
}
def main(args: Array[String]): Unit = {
(new Object with A).foo() //output: A
(new Object with A with B).foo() // output: B A
//those won't compile
//(new Object with B).foo()
//(new Object with B with A).foo()
}
现在开始打字:我写了一个像这样的特征:
trait C {
self: { def foo(): Unit } =>
abstract override def foo(): Unit = { println("B"); self.foo() }
}
请注意,super.foo()
不起作用。 Scala认识到abstract override
是合法的(并且它不会没有自我类型),但是对代理的调用是通过self
。到目前为止,这么好,但那是我偶然发现的地方:
(new Object with A with C).foo()
给出以下错误消息:
在
foo
类型的特征A
中覆盖方法()Unit
;类型为foo
的特征C
中的方法()Unit
无法覆盖具体成员而没有被两者覆盖的第三个成员(此规则旨在防止意外覆盖'')
我并不完全明白“[除非有]第三个被两个人覆盖的成员”,但最终它不起作用。是否是一个错误(因为abstract override
不能解决这些问题并且它应该有效),abstract override
的实施限制,或者真正有用的错误(因为abstract override
确实是危险的我不知道。
所以,抱歉,我最终无法帮助你。我会继续提出这些后续问题:
C
,还是总能得到错误?(如果您要问这些问题,请留下一个链接,这对我来说也很有趣)