2015-08-25 4 views

Antwort

8

Es scheint wirklich, wie sollten Sie in der Lage sein, zu schreiben

trait X[T <: X[T]] 
object Y extends X[Y.type] 

jedoch, wenn Sie versuchen, dass der Compiler Sie nicht hilfreich geben (und ich denke, unechte) Fehler,

scala> object Y extends X[Y.type] 
<console>:16: error: illegal cyclic reference involving object Y 
     object Y extends X[Y.type] 

ich sage „unecht“ weil wir ein äquivalentes Objekt mit einem wenig zusätzlichen Infrastruktur bauen können,

trait X[T <: X[T]] 

trait Fix { type Ytype >: Y.type <: Y.type; object Y extends X[Ytype] } 
object Fix extends Fix { type Ytype = Y.type } 
import Fix.Y 

Wenn Sie mit echtem Code experimentieren wollten, würde die Verwendung eines Paketobjekts anstelle von object Fix dieses Idiom ein wenig nützlicher machen.

+0

Glaubst du, das ist ein Compiler Bug oder ist es ein Versehen in der Spezifikation? Oder vielleicht gibt es etwas Subtilität, die wir nicht sehen, die den Fehler notwendig macht? –

+3

Ein Gespräch mit @retronym auf [scala/scala] (https://gitter.im/scala/scala?at=55dc7303fcfd5a7865af45d4) deutet darauf hin, dass es sich um einen Fehler handelt. Und es funktioniert [wie erwartet auf Dotty] (https://gitter.im/lampepfl/dotty?at=55dc95a3a6bcd8894068e278). –

+0

https://github.com/scala/bug/issues/9844 –

1

ändern Sie es an:

trait Y extends X[Y] 

object ist kein Typ in Scala, aber das so genannte Begleitobjekt. Durch die Definition object Y können Sie nicht ausdrücken, dass es trait T[Y] erweitern sollte, da sich die zweite Y auf einen Typ Y bezieht, der nicht definiert wurde. Sie können die folgenden jedoch tun:

trait Y extends X[Y]   //If you try this on the REPL, do :paste before 
object Y extends X[Y] 

In diesem Fall wird das Objekt YX[Y] erstreckt, wo die zweite Y das Merkmal ist, dass Sie nur definieren, stellen Sie sicher, dass Sie dies im Auge behalten.

+0

Ich möchte, dass Y nur einmal instanziert wird und auf seine eindeutige Instanz zugreift, deshalb brauche ich ein Objekt. –

+0

Dann können Sie den Konstruktor mit 'Klasse Y private() extends X [Y]' privat machen und diese Instanz öffentlich verfügbar machen. – Chirlo