特质实施

时间:2010-04-28 12:28:53

标签: scala traits

如果我有一些特征:

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

我可以用两种方式编写类(C1和C2添加相同的功能)

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

哪种变体更好(有效)?

1 个答案:

答案 0 :(得分:4)

它们在性能方面完全相同。如果你写这样的测试:

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 { }
}

并查看您看到的DessertSalad的字节码

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

如果您继续查看C1C2的初始值设定项,则它们都是空的。如果您再次查看c的方法调用,则它是对C1C2中定义的方法的引用。

这是因为解释了分层特征的方式。您可以将它们视为一个堆栈:每次添加“with”时,整个继承层次结构都会被压入堆栈,除了之外的任何东西都不会再添加。因此,C2是否有B并不重要,因为类Salad已经选择了B,因为它扩展了B