7

I have this code:

trait base{
  def msg: Unit= {
    println{"base"}
  }
}

trait foo extends base {
  abstract override def msg: Unit ={
    super.msg
    println("foo")
  }
}

class base2{
  def msg:Unit = {
    println{"base 2"}
  }
}

class test extends base2 with foo{
   override def msg: Unit ={
    super.msg
    println("done")
  }
}

If I call (new test).msg, this prints out things like: base, foo, done

However, if I change the base trait to:

trait base{
  def msg: Unit
}

it prints out things like: base 2, foo, done

I understand the order of with is from right to left (last one comes first) but how about extends? How come sometimes it prints base2, but sometimes base?

giampaolo
  • 6,906
  • 5
  • 45
  • 73
Sonya
  • 71
  • 1
  • 4
  • This kind of weirdness is why I avoid the cake pattern. – samthebest Dec 20 '14 at 12:34
  • If it works like in Groovy, then you need to add `super.msg` to `base` trait, so it chains to your `base2` class. Without having implementation in `base`, `base2` is called via `foo`'s `super.msg`. – MaciejGórski Mar 15 '15 at 22:29

2 Answers2

1

When you omit the implementation, base is a template of a trait and has different evaluation rules. See the Scala specification

WeaponsGrade
  • 878
  • 5
  • 13
1

Scala has something called type linearization. It defines initialization order. Read here http://eed3si9n.com/constraining-class-linearization-in-Scala

bkowalikpl
  • 817
  • 5
  • 11