Es scheint einen Unterschied zu machen, ob Sie this.type
aus einer Eigenschaft oder aus dem Bereich, in dem das Objekt erstellt wird, beziehen, mit überraschenden Ergebnissen.Überraschende Äquivalenzen und Nicht-Äquivalenzen bezüglich this.type
import scala.reflect.runtime.universe._
trait Trait {
val ttag = typeOf[this.type]
println(s"Trait constructor: $this")
}
object Instance1 extends Trait
object Instance2 extends Trait
println(typeOf[Instance1.type] =:= typeOf[Instance2.type]) // Should be false
println(Instance1.ttag =:= Instance2.ttag) // Should be false
println(Instance1.ttag =:= typeOf[Instance1.type]) // Should be true
Hier ist der Ausgang:
false // As expected: the singleton types of two objects are different.
Trait constructor: [email protected]
Trait constructor: [email protected]
true // But the this.type tags are equivalent
false // and the this.type tag is not equivalent to the singleton type.
So gibt es zwei verschiedene Objekte, aber anscheinend ist jeweils einen äquivalenten Typ-Tag bekommt für seine this.type
, die die .type
des Objektes nicht gleichwertig ist von einem umschließenden Umfang gesehen.
Ist das ein Compiler-Bug oder, wenn nicht, könnten Sie erklären, warum dieses Verhalten sinnvoll ist?
(Ich bin mit Scala 2.11.2. Ich habe es versucht, mit einem self
alias für this
, mit dem gleichen Ergebnis.)
Für das, was es wert ist, wenn ich starte deinen Code Ich erhalte einen internen Compilerfehler. Ein Compiler-Fehler scheint also nicht unwahrscheinlich. Eine weitere Möglichkeit, zu experimentieren, besteht darin, eine Methode zu verwenden, die den Typ eines lokalen Objekts zurückgibt. – Owen
@Owen Basierend auf unserer Konversation unten, meiner Suche durch die Spezifikation und einer Suche in der Problemdatenbank, ging ich weiter und postete meinen [ersten Scala-Fehler] (https://issues.scala-lang.org/browse/SI -9439). Ich hoffe es ist kein Duplikat oder eigentlich kein Bug! –
Mein aktuelles Verständnis (aufbauend auf Owens und Jason Zauggs Kommentaren): Jeder pfadabhängige Typ hat ein "Präfix", das angibt, wo das Objekt in seinem Umfang zu finden ist. Die Typäquivalenzprüfung prüft das Präfix, nicht das Objekt selbst (das nur zur Laufzeit existiert und möglicherweise nie erstellt wird). Innerhalb 'Trait' hat' this.type 'das Präfix 'Trait', was zum Typ' Trait.this.type' führt - für alle Instanzen. 'Instance1.type' hat ein Präfix, das besagt, dass das Objekt im Top-Level-Bereich definiert ist, mit dem Namen' Instance1', was zum Typ 'Instance1.type' führt - anders als innerhalb von' Trait'. –