假设我有以下代码:
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)
}
}
当我混入Trait1
和Trait2
时,引用Inner
似乎默认为Inner
类型,其中我混合的第二个特征;所以当我调用Obj
的{{1}}方法时,会打印main
。如何在Inner2
中引用Trait1.Inner
?以下所有三个都会产生编译器错误:
Foo
答案 0 :(得分:6)
而不是
class Concrete1 extends Inner
使用此
class Concrete1 extends super[Trait1].Inner
那应该能得到你想要的东西
答案 1 :(得分:4)
模板中有两个名称空间(模板是类,对象或特征的主体。)
从多个父模板继承时,这些名称空间中的冲突将通过类线性化来解决。
您可以重新订购继承,将所需的父级内部版本添加到您的课程中,或者找到替代设计。
答案 2 :(得分:3)
一个选项(如果您可以侵入特征)是将每个内部特征定义为具有非冲突名称的类型成员。
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
}
答案 3 :(得分:2)
为什么不按照您希望它们具有优先顺序排列特征?特征的线性化不是任意的,而是指定的。