我想拥有一个特征,可以将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")
有什么办法吗?
注意,我不控制A和B。它们来自另一个我无法修改的库。
[编辑-在看到答案后添加]
有没有办法像这样调用原始方法?
trait ImplementsStuff {
this: HasStuffMethod =>
abstract override def stuff = "foo" + "how do I call the original method here?"
}
这没有用,因为当您将其混合成某种东西时,它会给出:
error: overriding method stuff in class A of type => java.lang.String; method stuff in trait ImplementsStuff of type => java.lang.String cannot override a concrete member without a third member that's overridden by both (this rule is designed to prevent ``accidental overrides'')
但这不是偶然的。是的,我确实希望您跨过现有方法。然后,我也称呼它。
最佳答案
我可以想到两种选择:
选项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")
选项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")
关于Scala特征和结构类型: can a trait extend a structural type and then call super?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9538728/