2017-08-24 3 views
0
class Foo { 
    def copy: this.type = new Foo().asInstanceOf[this.type] 
    def multiply(n: Int): Seq[this.type] = (0 until n).map(_ => copy) 
} 

Dieser Code nicht wie mit einem Fehler kompilieren:`this.type`: Warum kompiliert das nicht?

<console>:33: error: type mismatch; 
found : scala.collection.immutable.IndexedSeq[Foo] 
required: Seq[Foo.this.type] 

ich nicht eine Erklärung für diese denken kann: this.typecopy kehrt, multiply gerade ruft .copy ... warum ist das Ergebnis nicht kompatibel?

Ist das ein Compiler Bug, oder gibt es einen tatsächlichen Grund, warum ich vermisse, warum das nicht funktionieren sollte?

Antwort

0

Es ist entweder ein Fehler oder eine JVM-Einschränkung. Erstellen Sie dazu einen Typalias für this.type in Foo, oder geben Sie explizit die Typparameter für map an.

Ich glaube jedoch nicht, dass es einen Anwendungsfall gibt, der eine Laufzeitumwandlung nach this.type erfordert. Was auch immer Sie verwenden, es sollte einen alternativen und besseren Ansatz geben.

+0

Ich stimme der Besetzung scheint eine wirklich schlechte Idee. Außerdem zieht es der Compiler vor, keinen Singletontyp in Abwesenheit einer Beschränkung zu folgern. 'Identität (foo)' ist 'Foo' nicht' foo.type', es sei denn 'object foo' zum Beispiel. –

+1

Eigentlich 'identity (foo): foo.type' aber nicht' identity (List (foo) .map (_ => foo)): Listet [foo.type] auf, so dass es wegen der 'CanBuildFrom'-Inferenz ist. –

0

Es ist nur diese Art Inferenz nicht Singletons abzuleiten. Dies ist kein Fehler, sondern eine bewusste Entscheidung für das Sprachdesign. Sie müssen explizite Parameter map geben:

(0 to n).map[this.type, Seq[this.type]] { _ => copy } 

Wenn Sie es so gewünscht wird, Sie verpflichtet, die Singleton Typ verwenden könnte, ein Verfahren zu schaffen, das Singleton Typen folgert:

def replaceAll[In, Elem <: Singleton, Out](coll: FilterMonadic[_, In])(e: Elem)(implicit cbf: CanBuildFrom[In, Elem, Out]): Out 
= coll.map { _ => e } 

Verbrauch:

replaceAll(0 to n)(x: x.type) // Won't work without ascription, but cleaner than above 

Verwenden Sie auch nicht asInstanceOf[this.type]. Singleton-Typen basieren auf der Referenzgleichheit, nicht equals. Deshalb erhalten Sie Sachen wie:

val foo = new Foo 
val foo2: foo.type = foo.copy 
foo2.isInstanceOf[foo.type] // false because foo2 neq foo 

Sie können F-bounds wollen, statt.

+0

aber siehe meinen Kommentar zu der anderen Antwort. –

+0

Warte ... Du sagst nicht, dass etwas wie 'def copy: this.type = clone(). AsInstanceOf [this.type]' nicht funktionieren sollte, oder? Weil es für mich funktioniert ... – Dima

+0

Ich meinte 'isInstanceOf' funktioniert nicht mehr. 'asInstanceOf' funktioniert gut, aber es sollte nicht so verwendet werden, da es' isInstanceOf' unterbricht. – HTNW

Verwandte Themen