One option (if you can be invasive to hell) is to define each Inner trait as a member of a type that has a non-conflicting name.
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)
If you cannot be invasive of the original traits (Trait1 and Trait2), you can expand them to define a type member.
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 }
Another approach would be to use an intermediate attribute to define your first concrete class:
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 }
Mitch blevins
source share