0
votes

I'm working my way through Odersky's Programming in Scala and I'm looking at the chapter on traits. He gives an example where various traits/classes are linearized and says this:

Cat -> FourLegged -> HasLegs -> Furry -> Animal -> AnyRef -> Any

When any of these classes and traits invokes a method via super, the implementation invoked will be the first implementation to its right in the linearization.

I've defined classes/traits as follows:

abstract class Animal { def hi }

class Cat extends Animal { def hi { println("cat") } }

trait Furry extends Animal { abstract override def hi { 
  println("furry"); super.hi } } 

and done

val c = new Cat with Furry
c.hi

and I get

furry
cat

According to the book, the super in furry should call Animal.hi Since Animal is abstract, that should either cause a compile error or a runtime error I would have thought. Instead it calls cat.hi What am I missing? I thought the Cat class would appear first in the linearization, and therefore there is no way that a super call could call it?

(I missed out HasLegs and FourLegged to keep it simpler)

I suspect they've mis-stated the linearization order?

Thanks!

EDIT: Following user2357112's comment below, I tried mixing in the Furry trait statically:

scala> class Cat extends Animal with Furry { def hi { println("cat") } }
<console>:13: error: overriding method hi in trait Furry of type => Unit;
 method hi needs `override' modifier
       class Cat extends Animal with Furry { def hi { println("cat") } }

I'm now rather confused as I thought that it didn't make a difference whether you mixed in a trait at runtime or in the code. But here, the runtime mixin executes without error, but I get a compile error if I try to mix it in in code. What gives?

1
The book's Cat is class Cat extends Animal with Furry with Fourlegged. with Furry is already part of Cat. - user2357112
Thanks @user2357112 - why would that make a difference? I thought that mixing in during runtime would be the same as mixing in statically as part of the build step? - Bruce

1 Answers

0
votes

According to this answer, the concrete class will be constructed first when using mixins, and linearization order is the opposite of construction order. Therefore, the construction is Animal -> Cat -> Furry, and the linearization is Furry -> Cat -> Animal, which is why you see "furry" first and "cat" second.