tags:

views:

66

answers:

1

If I have some traits like:

trait A {...}
trait B extends A{...}
trait C1 extends B{...}
trait C2 extends A{...}

I can write class in two ways (C1 and C2 add same functionality)

class Concrete1 extends B with C1
class Concrete2 extends B with C2

What variant is better(efficient)?

+2  A: 

They are identical in terms of performance. If you write a test like this:

object Traits {
  trait A { def a = "apple" }
  trait B extends A { def b = "blueberry" }
  trait C1 extends B { def c = "cherry" }
  trait C2 extends A { def c = "chard" }
  class Dessert extends B with C1 { }
  class Salad extends B with C2 { }
}

and look at the bytecode for Dessert and Salad you see

public Traits$Dessert();
  Code:
   0:   aload_0
   1:   invokespecial   #29; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   invokestatic    #33; //Method Traits$A$class.$init$:(LTraits$A;)V
   8:   aload_0
   9:   invokestatic    #36; //Method Traits$B$class.$init$:(LTraits$B;)V
   12:  aload_0
   13:  invokestatic    #39; //Method Traits$C1$class.$init$:(LTraits$C1;)V
   16:  return

public Traits$Salad();
  Code:
   0:   aload_0
   1:   invokespecial   #29; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   invokestatic    #33; //Method Traits$A$class.$init$:(LTraits$A;)V
   8:   aload_0
   9:   invokestatic    #36; //Method Traits$B$class.$init$:(LTraits$B;)V
   12:  aload_0
   13:  invokestatic    #39; //Method Traits$C2$class.$init$:(LTraits$C2;)V
   16:  return

If you then go and look at the initializers for C1 and C2, they're both empty. If you look at the method call for c, again, it's a reference to the one defined either in C1 or C2.

This happens because of the way layered traits are interpreted. You can think of them as a stack: each time you add a "with", the whole inheritance hierarchy is pushed onto the stack except that anything already there is not added again. So it doesn't matter whether C2 has B or not, since the class Salad already picked up B because it extends B.

Rex Kerr