2010-04-28 169 views
3

如果我有一些特点,如:特质实施

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

如果C1和C2添加相同的功能,他们为什么分开? – RoToRa 2010-04-28 12:31:55

+0

方法调用的运行时效率?程序员效率的可读性? – 2010-04-28 13:51:07

+0

@Mitch Blevins方法调用的运行时效率(我正在考虑具体的{1,2}实例化时间) @继承中的差异 - 它扩展了不同的类,但具有相同的f功能 – Jeriho 2010-04-28 14:22:46

回答

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