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)
  }
}

当我混入Trait1andTrait2时,引用Inner似乎默认为Inner我混入第二个特征的类型;所以当我调用它Objmain方法时,它会打印出来Inner2。我如何引用Trait1.Innerin Foo?以下所有三个都会产生编译器错误:

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

模板中有两个命名空间(模板是类、对象或特征的主体。)

  1. 成员:vals、vars、defs 和嵌套对象
  2. 类型:类型别名、嵌套特征和嵌套类

当从多个父模板继承时,这些命名空间中的冲突通过类线性化来解决。

您可以重新排序继承以将所需的父 Inner 带入您的类,或找到替代设计。

于 2010-01-15T17:56:25.020 回答
3

一种选择(如果您可以侵入特征)是将每个 Inner 特征定义为具有非冲突名称的类型成员。

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 回答