Messed up trait linearisation?

linearization, multiple-inheritance, scala, traits

Solution

It's best to go to the Spec for this kind of thing. The algorithm is described at `5.1.2 Class Linearization`

Paraphrasing it, the Linearization of a class C is C followed by Linearization of the things it extends starting with the rightmost item. Then there is the final step of removing duplicates in the Linearization, keeping only the rightmost ones.

So in your example for `Compound1` (ignoring built ins like AnyRef): `L(Compound1) = Compound1 + L(Event) + L(Standalone)` `L(Event) = Event + L(Selector)` `L(Selector) = Selector` `L(Standalone) = Standalone + L(Event) + L(Node)` `L(Node) = Node` Putting it together: `L(Compound1) = Compound1 Event Selector Standalone Event Selector Node` Removing the duplicates: `Compound1 Standalone Event Selector Node`

For `Compound2` it ends up being: `Compound2 Standalone Node Event Selector`

As for the other question, I think the easiest way would be to override the method in `Standalone` and call the desired method in the super class.

trait Standalone extends Node with Event { override def hashCode = super[Event].hashCode }  

Assuming this is not what you meant by "copying".

Problem

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.

Original source