score:9

Accepted answer

are these arbitrary conventions, as good as any other one?

no, these are not arbitrary. the linearization is done this way because it's the only way that will give you a sane method resolution order (mro).

why traits are explored first than classes and not vice versa ?

this is only true for a given class definition, in that the traits it extends come before the class it extends. this follows from the fact that the super classes/traits are explored right-to-left—which brings us to your second point.

why traits are traversed right to left, instead of left to right ?

here's a very simple motivating example for this.

type mytype = t1 with t2
// creating new instance using alias
new mytype with t3
// creating new instance directly
new t1 with t2 with t3

we would expect both instances in the example above to have the same linearization. when using type aliases, we "stack" additional traits on the right-hand-side, therefore we'd expect the traits on the right-hand-side to have highest precedence in the mro, and therefore come first in the linearization.

here's a quick example i came up with illustrating the linearization of traits and classes:

class base { override def tostring = "base" }
trait a { abstract override def tostring = "a " + super.tostring }
trait b { abstract override def tostring = "b " + super.tostring }
trait c { abstract override def tostring = "c " + super.tostring }
trait d { abstract override def tostring = "d " + super.tostring }
trait e { abstract override def tostring = "e " + super.tostring }
trait f { abstract override def tostring = "f " + super.tostring }
class x extends base with a with b { override def tostring = "x " + super.tostring }
class y extends x with c with d { override def tostring = "y " + super.tostring }
class z extends y with e with f { override def tostring = "z " + super.tostring }
new z
// res0: z = z f e y d c x b a base

you can see from the tostring output that the linearization here is z f e y d c x b a base, which is exactly what i'd expect with the given hierarchy. for example, since z extends y, which mixes-in the trait c, we would expect y's behaviors to come before c, but after z and its mix-ins e and f.

a simple reference on this chapter 12 of programming in scala, first edition: traits. (i don't think this has changed recently, so the first edition should still be accurate.)


Related Query

More Query from same tag