I want to to extend a trait within a trait, like this:
trait NodeTypes {
trait Node {
def allNodesHaveThis: Int
}
}
trait ScrumptiousTypes extends NodeTypes {
trait Node extends super.Node {
def scrumptiousness: Int
}
}
trait YummyTypes extends NodeTypes {
trait Node extends super.Node {
def yumminess: Int
}
}
object Graph extends NodeTypes with ScrumptiousTypes with YummyTypes {
case class Node() extends super.Node {
override def allNodesHaveThis = 1
override def scrumptiousness = 2 // error: ScrumptiousTypes.Node has been disinherited
override def yumminess = 3
}
}
If this works, it would be a nice way of saying “When your Graph
inherits from <Whatever>Types
, its Node
class must provide the methods required by <Whatever>
.”
But the Scala 2.11.2 compiler says:
error: method scrumptiousness overrides nothing
override def scrumptiousness = 2
^
It appears that YummyTypes.Node
shadows ScrumptiousTypes.Node
, following the usual way that Scala resolves “diamond” inheritance for methods: by type linearization. As I understand things, that should be OK, though, because YummyTypes.Node
explicitly extends super.Node
, which, by the same type linearization, should refer to ScrumptiousTypes
.
What have I misunderstood? Or, what does super.Node
refer to—and why?
If you're wondering why I'm doing this, it's so I can mix changes into several traits at once, so the inherited traits interoperate, as explained in this question. In the final Node class (and other classes that it works with), I don't want to explicitly extend from each Node trait: I want to mix in from one "thing" (whatever it is) and get all the mutually consistent changes made to Node and the other traits, all in a bundle. Or, if one trait defines a bunch of extensions to Node, extending from ScrumptiousTypes should make all of the Node-extensions contain a scrumptiousness
member, without having to list all the Node-extensions: trait Hypernode extends ScrumptiousTypes.Node
, trait ZealousNode extends ScrumptiousTypes.Node
, etc.