Here is a trait linearisation puzzler that causes me headaches. I have basically type Node
which defines equals
and hashCode
to be compared against other Node
s. And I have a Selector
type which may wrap a Node
along with extra data, and thus has its own equals
and hashCode
to be compared against other Selector
s.
Now I have a Standalone
type which combines Node
and Selector
, but I get inconsistent (?) linearisation with respect to equals
and hashCode
:
trait Selector { override def hashCode = 1 }
trait Event extends Selector
trait Node { override def hashCode = 2 }
trait Standalone extends Node with Event
Now all is fine (the more specific hashCode 1 is called) when I extend from either Event
or Standalone
:
object Single1 extends Event
Single1.hashCode // 1 -- ok
object Single2 extends Standalone
Single2.hashCode // 1 -- ok
It is also fine if I extend from both in this order:
object Compound1 extends Standalone with Event
Compound1.hashCode // 1 -- Ok
But it messes up when I do this:
object Compound2 extends Event with Standalone
Compound2.hashCode // 2 -- no!!!!!!!!
I made a little .dot diagram (mixins are ordered from left-to-right):
So, if I understand linearisation rules correctly, I should always end up with the hashCode
implemented by Selector
. The only explanation for this behaviour would be that there is some sort of greedy/depth-first thing involved...?
Also, if there is a technique I can use to make sure that whenever Standalone
is mixed in, it is ensured that Selector
overrules Node
(other than copying equals
and hashCode
from Selector
to Standalone
), that would be very much appreciated.
This is with Scala 2.9.2.