3

次のような特性がある場合:

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

クラスは 2 つの方法で記述できます (C1 と C2 は同じ機能を追加します)。

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

どのバリアントが優れていますか(効率的ですか)?

4

1 に答える 1

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持っているかどうかは関係ありません。BSaladBB

于 2010-04-28T17:42:44.890 に答える