2010-04-28 168 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