我希望有一个特点,可以a)用特定方法混合到任何类中,并且b)可以调用super.像这样的东西:
// A and B are from a library that I don't control. No changes allowed here.
class A {
def stuff = "a stuff"
}
class B {
def stuff = "b stuff"
}
// My code starts here
type HasStuffMethod = {
def stuff: String
}
// Note that this doesn't compile - gets:
// class type required but AnyRef{def stuff: String} found
trait ImplementsStuff extends HasStuffMethod {
override def stuff = "trait + " + super.stuff
}
val a = new A with ImplementsStuff
assert(a.stuff == "trait + a stuff")
val b = new B with ImplementsStuff
assert(b.stuff == "trait + b stuff")
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?
请注意,我不控制A和B; 他们来自另一个我无法修改的图书馆.
[编辑 - 看到答案后添加]
有没有办法在这样的东西中调用原始方法?
trait ImplementsStuff {
this: HasStuffMethod =>
abstract override def stuff = "foo" + "how do I call the original method here?"
}
Run Code Online (Sandbox Code Playgroud)
这没用,因为当你把它混合成它给出的东西时:
错误:覆盖类型=> java.lang.String的类A中的方法内容; 特征中的方法东西类型=> java.lang.String的ImplementsStuff不能覆盖具有被第二个成员覆盖的具体成员(此规则旨在防止"意外覆盖")
但这不是偶然的; 是的,我真的希望你完全采用现有的方法.然后让我也称之为.
我可以想到两个选择:
选项1,使用自我类型注释并stuff
从新方法(我想象中称为callStuff
)调用而不是覆盖它.
trait ImplementsStuff {
this: HasStuffMethod =>
def callStuff = "trait + " + this.stuff
}
val a = new A with ImplementsStuff
assert(a.callStuff == "trait + a stuff")
val b = new B with ImplementsStuff
assert(b.callStuff == "trait + b stuff")
Run Code Online (Sandbox Code Playgroud)
选项2(因为你说你不控制A和B)是亲爱的旧装饰模式.
trait HasStuff { def stuff: String }
class DecorateStuff(decorated: HasStuffMethod) extends HasStuff {
def stuff = "trait + " + decorated.stuff
}
val decA = new DecorateStuff(new A)
assert(decA.stuff == "trait + a stuff")
val decB = new DecorateStuff(new B)
assert(decB.stuff == "trait + b stuff")
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2347 次 |
最近记录: |