7

次のコードがあるとします。

trait Trait1 { 
  trait Inner {
    val name = "Inner1"
  }
}

trait Trait2 {
  trait Inner {
    val name = "Inner2"
  }
}

class Foo extends Trait1 with Trait2 {
  // I want Concrete1 to be a Trait1.Inner not a Trait2.Inner
  class Concrete1 extends Inner
  val c = new Concrete1
}

object Obj {
  def main(args: Array[String]): Unit = {
    val foo = new Foo
    println(foo.c.name)
  }
}

と を混ぜるTrait1Trait2、 を参照すると、 2 番目にミックスした特性Innerの型がデフォルトのように見えます。だから私はのメソッドInnerを呼び出すと、それが印刷されます。で参照するにはどうすればよいですか? 次の 3 つすべてでコンパイラ エラーが発生します。ObjmainInner2Trait1.InnerFoo

class Concrete1 extends Trait1.Inner
class Concrete1 extends Trait1$Inner
class Concrete1 extends Trait1#Inner
4

4 に答える 4

6

それ以外の

class Concrete1 extends Inner

これを使って

class Concrete1 extends super[Trait1].Inner

それはあなたが望むものを手に入れるはずです

于 2010-01-16T03:23:51.773 に答える
4

テンプレート内には 2 つの名前空間があります (テンプレートは、クラス、オブジェクト、または特性の本体です)。

  1. メンバー: vals、vars、defs、およびネストされたオブジェクト
  2. 型: 型エイリアス、ネストされたトレイト、およびネストされたクラス

複数の親テンプレートから継承する場合、これらの名前空間の競合は、クラスの線形化によって解決されます。

継承の順序を変更して、目的の親 Inner をクラスに取り込むか、別の設計を見つけることができます。

于 2010-01-15T17:56:25.020 に答える
3

1 つのオプション (特性に侵入できる場合) は、各内部特性を競合しない名前を持つ型メンバーとして定義することです。

trait Trait1 {
  type Inner1 = Inner
  trait Inner {
    val name = "Inner1"
  }
}

trait Trait2 {
  type Inner2 = Inner
  trait Inner {
    val name = "Inner2"
  }
}

class Foo extends Trait1 with Trait2 {
  class Concrete1 extends Inner1
  class Concrete2 extends Inner2
  val c1 = new Concrete1
  val c2 = new Concrete2
}

object App extends Application {
  val foo = new Foo
  println(foo.c1.name) // Inner1
  println(foo.c2.name) // Inner2
}

元の特性 (Trait1 および Trait2) に侵襲できない場合は、それらを拡張して型メンバーを定義できます。

trait Trait1 {
  trait Inner {
    val name = "Inner1"
  }
}
trait Trait2 {
  trait Inner {
    val name = "Inner2"
  }
}

trait Trait1a extends Trait1 {
  type Inner1 = Inner
}
trait Trait2a extends Trait2 {
  type Inner2 = Inner
}

class Foo extends Trait1a with Trait2a {
  class Concrete1 extends Inner1
  class Concrete2 extends Inner2
  val c1 = new Concrete1
  val c2 = new Concrete2
}

別のアプローチは、中間の特性を使用して最初の具体的なクラスを定義することです。

trait Trait1 {
  trait Inner {
    val name = "Inner1"
  }
}
trait Trait2 {
  trait Inner {
    val name = "Inner2"
  }
}

trait FooIntermediate extends Trait1 {
  class Concrete1 extends Inner
}

class Foo extends FooIntermediate with Trait2 {
  class Concrete2 extends Inner
  val c1 = new Concrete1
  val c2 = new Concrete2
}
于 2010-01-15T18:15:35.380 に答える
2

優先順位があると予想される順序で特性を並べてみませんか? 特性の線形化は恣意的ではなく、指定されています。

于 2010-01-15T17:48:44.227 に答える