2012-04-18 7 views
8

Ich möchte abstrakten Typ in Merkmal mit <: und nicht mit = überschreiben (wie Antwort hier Scala Upper Bounds : value is not a member of type parameter).Kuchenmuster mit übergeordneten abstrakten Typ funktioniert nicht mit oberen Typ Grenzen

Ich möchte Kuchenmuster verwenden, aber das funktioniert nicht, ich verstehe nicht warum?

trait A { 
    def ping = println("ping") 
} 

trait Cake { 
    type T 
} 

trait S { this: Cake => 
    type T = A 
    def t: T 
    t.ping 
} 

OK, dieses Beispiel laufen, aber in meinem realen Anwendungsfall mag ich Typen mit <: außer Kraft zu setzen und nicht mit = .Es scheint unmöglich, die t-Funktion zugreifen zu können, warum?

trait S { this: Cake => 
    type T <: A 
    def t: T 
    t.ping 
} 

Rückkehr ein Fehler value ping is not a member of S.this.T

Antwort

15

Es ist ein Manko des Typs Systems Scala. Bei der Festlegung der Mitglieder in einem Mixin verwendet Scala zwei Regeln: Erstens überschreibt concrete immer abstrakt. Zweitens, wenn zwei Mitglieder beide konkret oder beide abstrakt sind, dann gewinnt derjenige, der später in der Linearisierungsreihenfolge kommt.

Darüber hinaus ist die Selbst Art eines Merkmals

trait S { this: C => ... } 

implizit

erweitert wird
trait S { this: S with C => ... } 

so, dass die Definitionen in der Eigenschaft S in S. In Ihrem Fall zugegriffen werden kann, das Merkmal S wird gesehen als:

trait S { this: S with Cake => 
    type T = A 
    def t: T 
    t.ping 
} 

Nun, solange T Beton ist, ist das in Ordnung, weil es die AB übersteuert stract T in Kuchen. Aber wenn T abstrakt ist, kommt der in Cake später in der Linearisierungsreihenfolge und gewinnt. Und das T hat keine Obergrenze, also kein Member-Ping. Eine Möglichkeit, dies zu beheben, ist die Linearisierung, um durch Schreiben zu ändern:

trait S { this: Cake with S => 
    type T <: A 
    def t: T 
    t.ping 
} 

Es wäre sauberer, wenn Scala eine andere Regel hat, die besagt, dass alle Einschränkungen der abstrakten Art Mitglieder in der mixin zusammengeführt werden, anstatt eine der Kommissionierung einzelnes Element gemäß der Linearisierungsreihenfolge. Das ist eine Änderung, die wir in Zukunft berücksichtigen wollen, aber wir müssen auf die Rückwärtskompatibilität achten.