如果新实例已经在类级别中组合,则将忽略该特征组合

时间:2014-06-19 07:50:08

标签: scala

以下是代码:

trait Foo {

  def get(x: Int): Int

}

trait Simple extends Foo {

  override def get(x: Int): Int = x

}

trait Add15 extends Foo {

  abstract override def get(x: Int): Int = x + 15

}

trait Add30 extends Foo {

  abstract override def get(x: Int): Int = {

    super.get(x) + 30
  }

}


class Queue extends Simple with Add15 with Add30

new Queue with Add30 get 0 // same as new Queue get 0, because with Add30 is ignored

我只是想知道编译错误而不是忽略它会更好吗?它就像

class Queue extends Simple with Add15 with Add30 with Add30会出现编译错误

非常感谢提前

1 个答案:

答案 0 :(得分:0)

with不会被忽略。

new t等同于new Queue with Add30 actually says的规范:

{ class a extends Queue with Add30 ; new a }

当然可以,但实际上是否编译到了那个?

事实上:

scala> new Queue with Add30
res8: Queue with Add30 = $anon$1@aa21042

scala> :javap -prv -
Binary file res8 contains $line18.$read$$iw$$iw$
[snip]
  private final $line12.$read$$iw$$iw$Queue res8;
    flags: ACC_PRIVATE, ACC_FINAL
[snip]
  public $line18.$read$$iw$$iw$();
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #19                 // Method java/lang/Object."<init>":()V
         4: aload_0       
         5: putstatic     #21                 // Field MODULE$:L$line18/$read$$iw$$iw$;
         8: aload_0       
         9: new           #23                 // class $line18/$read$$iw$$iw$$anon$1
        12: dup           
        13: invokespecial #24                 // Method $line18/$read$$iw$$iw$$anon$1."<init>":()V
        16: putfield      #17                 // Field res8:L$line12/$read$$iw$$iw$Queue;
        19: return   

因此结果值只是Queue,但是您实例化了一个匿名的子类,它可以简单地扩展它。我太懒了(我的意思是忙)试试-optimize

您可以回答问题并询问为什么with T with T抱怨trait T is inherited twicelinearization无法处理冗余?

我认为a从线性化中消失的第二种情况是这样的:

scala> class X
defined class X

scala> trait Y extends X
defined trait Y

scala> new X with Y
res15: X with Y = $anon$1@5af97169

您正在混合已扩展Y的{​​{1}}。

但是现在我必须使用我正在为其主要用例涂鸦的餐巾纸(餐巾纸)并回到我以前做过的事情。