Scala Stackable Features

For the code below, as far as I understand, the linearization of the expression

new E with D with C with B

- E โ†’ C โ†’ B โ†’ D. So, then there should be no expression d.foo () in the code

ECBD instead of CBDE is rated lower. What am I missing?

trait A { def foo(): String = "" } trait B extends A { abstract override def foo() = "B" + super.foo() } trait C extends B { abstract override def foo() = "C" + super.foo() } trait D extends A { abstract override def foo() = "D" + super.foo() } class E extends A{ override def foo() = "E" } var d = new E with D with C with B; d.foo() //prints CBDE 

I noticed that if I have class F as below

 class F extends A with D with C with B{ override def foo() = "F" + super.foo() } 

and do

 new F().foo 

he prints "FCBD"

It seems a little incompatible with me, because the class F mixes the same way as the expression, but has a different print order

+7
scala traits
source share
1 answer

The first case of new E with D with C with B perfectly explained here . Its linearization is EDBC , so when you call d.foo() , it

  • first calls C#foo() ,
  • then B#foo() ,
  • then D#foo()
  • and finally E#foo() .

If you make an E trait and mix it at the end: val d = new D with C with B with E , then d.foo() will only return "E" because trait E is the โ€œlastโ€ in the linearization and just overrides foo .

Case F is different because you define foo as "F" + super.foo() , and super in this case A with D with C with B , whose linearization is ADBC , so new F().foo() prints first "F" , then its super.foo() , which is equal to "CBD" .

By the way, try changing A#foo() to return "A" , then you will see that you redefine A foo in E , so "A" will not appear as a result, and in F it is "FCBDA" .

+4
source share

All Articles