4

Scala code:

trait X

trait Y1 {
  this: X => 
}

trait Y2 extends X {
}

I wonder what's the difference between Y1 and Y2 traits? If I have a class Z need to extend Y:

class Z1 extend Y1 with X

class Z2 extends Y2

It seems there is no difference for the two classes Z1 and Z2. If they are nearly the same, which style would you recommend?

Freewind
  • 193,756
  • 157
  • 432
  • 708
  • Major difference for me is in scalac errors. In case of self dependence they are much more cryptic. – Eugene Zhulenev May 03 '14 at 04:24
  • Possible duplicate of http://stackoverflow.com/questions/1990948/what-is-the-difference-between-scala-self-types-and-trait-subclasses – Nonos May 09 '14 at 18:59

2 Answers2

2

Sometimes, you're in a deeply nested scope, and the alias is useful for the outer object, for instance here.

As explained here, the linearizations of the two types for this are inverted.

That is, you have this: Y with X and this: X with Y.

this matters (pun intended):

scala> trait X { type T }
defined trait X

scala> trait Y { type T <: String ; def t: T ; def f = t.length }
defined trait Y

scala> trait Y { this: X => type T <: String ; def t: T ; def f = t.length }
<console>:8: error: value length is not a member of Y.this.T
       trait Y { this: X => type T <: String ; def t: T ; def f = t.length }
                                                                    ^

scala> trait Y { this: X with Y => type T <: String ; def t: T ; def f = t.length }
defined trait Y

scala> trait Y extends X { type T <: String ; def t: T ; def f = t.length }
defined trait Y

But as the linked, authoritative answer says, it may not matter forever.

Community
  • 1
  • 1
som-snytt
  • 39,429
  • 2
  • 47
  • 129
1

trait B extends A means that B is an A.

trait B { this: A => } is dependency injection - you want B to require A.

Consider these two REPL sessions:

> trait A
defined trait A

> trait B extends A
defined trait B

> class C
defined class C

> new C with A
res0: C with A = $anon$1@706abf59

> new C with B
res1: C with B = $anon$1@2004aa19

And this:

> trait A
defined trait A

> trait B { this : A => }
defined trait B

> class C
defined class C

> new C with A
res0: C with A = $anon$1@1ef535db

> new C with B
<console>:11: error: illegal inheritance;
 self-type C with B does not conform to B's selftype B with A
          new C with B
                     ^
Snnappie
  • 178
  • 1
  • 7
  • Also I just came across [this](http://stackoverflow.com/questions/1990948/what-is-the-difference-between-scala-self-types-and-trait-subclasses) - the accepted answer does a much better job of explaining this than I did. – Snnappie May 03 '14 at 04:27