0

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?

Bruce
  • 2,406
  • 5
  • 29
  • 35
  • The book's `Cat` is `class Cat extends Animal with Furry with Fourlegged`. `with Furry` is already part of `Cat`. – user2357112 Oct 06 '18 at 20:55
  • 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 Oct 06 '18 at 21:08

1 Answers1

0

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.

Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
  • Thanks, but I'm not sure what you say makes sense. If the concrete class is constructed first, and linearization is the opposite order, then surely the concrete class - Cat - should come first, but you have it between Furry and Animal? – Bruce Oct 06 '18 at 21:15
  • 2
    @Bruce The construction proceeds `Any -> AnyRef -> Animal -> Cat -> Furry`. The linearization order is `Furry -> Cat -> Animal -> AnyRef -> Any`. – HTNW Oct 06 '18 at 23:19