Alex Rivera | Logout

Scala traits and structural types: can a trait extend a structural type and then call super?

Asked 2012-03-02T18:48:25.697
9

I'd like to have a trait that can a) be mixed into any class with a particular method, and b) can call super. Something like this:

  // 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")

Is there any way to do this?

Note that I don't control A and B; they're coming from another library that I can't modify.

[Edit - added after seeing answers]

Is there a way to call the original method in something like this?

  trait ImplementsStuff {
    this: HasStuffMethod =>
    abstract override def stuff = "foo" + "how do I call the original method here?"
  }

This isn't useful, since when you mix it into something it gives:

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'')

But it's no accident; yes, I really do want you to step all over that existing method. And then let me call it, too.

Edit
Report

1 Answer

4

You need an abstract override in such a case.

answered 2012-03-02T19:26:52.117

Your Answer