如果我有一些特征,例如:
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
什么变体更好(有效)?
它们在性能方面是相同的。如果您编写这样的测试:
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 { }
}
并查看字节码Dessert
,Salad
你会看到
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
如果您然后去查看 and 的初始化程序C1
,C2
它们都是空的。如果您再次查看 的方法调用,它是对在或c
中定义的方法的引用。C1
C2
发生这种情况是因为解释分层特征的方式。您可以将它们视为一个堆栈:每次添加“with”时,整个继承层次结构都会被压入堆栈,除非已经存在的任何内容都不会再次添加。所以不管C2
有B
没有,因为这个类Salad
已经被选中了,B
因为它扩展了B
。