特征实现

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
方法调用的运行时效率?程序员的可读性效率? - Mitch Blevins
@Mitch Blevins 方法调用的运行时效率(我在考虑Concrete{1,2}实例化时间) @继承中的差异 - 继承自不同的类,但具有相同的功能。 - Jeriho
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是否具有BSalad类已经通过扩展B获取了B,所以这并不重要。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接