Scala特征和结构类型:特征是否可以扩展结构类型然后调用super?

Jam*_*ore 9 scala

我希望有一个特点,可以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不能覆盖具有被第二个成员覆盖的具体成员(此规则旨在防止"意外覆盖")

但这不是偶然的; 是的,我真的希望你完全采用现有的方法.然后让我也称之为.

Pao*_*lla 5

我可以想到两个选择:

选项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)


Dan*_*ral 4

abstract override在这种情况下你需要一个。