2012-05-31 10 views
5

Jak można def someA (w trait B) używać trait A z tym samym C#MyType jak w B? (Następnie: A#MyType =:= B#MyType)Formy i typy ciast

trait C { 
    type MyType 
} 


trait A { 
    self: C => 
    def doSomething(s: MyType) { println(s.toString)} 
} 

trait B { 
    self: C => 

    def someA: A 
    def myType: MyType 

    def action = someA.doSomething(myType) 
} 

// Mix part 

case class Ahoy(value: String) 

trait ConcreteC extends C { 
    type MyType = Ahoy 
} 


class PieceOfCake extends B with ConcreteC { 
    val someA = new A with ConcreteC 
    val myType = Ahoy("MyType") 

} 

Nie kompiluje: niedopasowanie typu;

[error] found : B.this.MyType 
[error] required: _1.MyType where val _1: A 
[error] def action = someA.doSomething(myType)) 

Odpowiedz

3

Można zadeklarować doSomething i myType użyć ścieżki niezależną wersję MyType, SomeType#MyType:

trait SomeType { 
    type MyType 
} 


trait A { 
    self: SomeType => 
    def doSomething(s: SomeType#MyType) { println(s.toString)} 
} 

trait B { 
    self: SomeType => 

    def someA: A 
    def myType: SomeType#MyType 

    def action = someA.doSomething(myType) 
} 
+0

Ok, kompiluje, ale nie można mieszać bardziej specyficznego SomeType z B. – jwinandy

0

Jestem całkiem pewien, że nie może tego zrobić, ponieważ typy ścieżek są tak niezależne że - jeśli A <> B, to A # T jest ściśle różne od B # T (tj. A # T będzie nigdy be =: = B # T).

Powiedziawszy, można bezpiecznie rzucać, więc zawsze możesz zrobić coś takiego, jak someA.doSomething(myType.asInstanceOf[someA#MyType]). Brzydki, ale działa.

+0

To nie działa? Mam na myśli, że nie możesz rzucić na niestabilny identyfikator. – jwinandy