Scala-Instanzwert-Scoping

Beachten Sie, dass diese und ähnliche Fragen bereits gestellt wurden, z. B. inVerweise weiterleiten - Warum wird dieser Code kompiliert?, aber ich fand die Antworten, um noch einige Fragen offen zu lassen, also versuche ich es noch einmal mit diesem Thema.

Innerhalb von Methoden und Funktionen ist die Wirkung derval Das Schlüsselwort scheint lexikalisch zu sein, d. h.

<code>def foo {
  println(bar)
  val bar = 42
}
</code>

nachgebend

<code>error: forward reference extends over definition of value bar
</code>

Innerhalb von Klassen gelten jedoch die Scoping-Regeln vonval scheint sich zu ändern:

<code>object Foo {
  def foo = bar
  println(bar)
  val bar = 42
}
</code>

Dies kompiliert nicht nur, sondern auch dieprintln im Konstruktor wird ergeben0 als Ausgabe beim Aufruffoo Nachdem die Instanz vollständig erstellt wurde, wird der erwartete Wert ermittelt42.

Es scheint also möglich zu sein, dass Methoden Instanzwerte weiterleiten, die schließlich initialisiert werden, bevor die Methode aufgerufen werden kann (es sei denn, Sie rufen sie natürlich vom Konstruktor aus auf), und Anweisungen innerhalb des Konstruktors Sie können Werte auf die gleiche Weise weiterleiten, indem Sie auf sie zugreifen, bevor sie initialisiert wurden, was zu einem albernen, willkürlichen Wert führt.

Daraus ergeben sich einige Fragen:

Warum tutval Verwenden Sie seine lexikalische Kompilierzeit Wirkung innerhalb von Konstruktoren?

Da es sich bei einem Konstruktor in Wirklichkeit nur um eine Methode handelt, scheint dies eher inkonsistent zu sein, um vollständig zu löschenvalKompilierungseffekt, der nur den üblichen Laufzeiteffekt aufweist.

Warum tutvaleffektiv verlieren ihre Wirkung der Deklaration einesunveränderlich Wert?

Der Zugriff auf den Wert zu unterschiedlichen Zeiten kann zu unterschiedlichen Ergebnissen führen. Mir scheint es, als würde ein Detail der Compiler-Implementierung herauskommen.

Wie könnten legitime Verwendungszwecke dafür aussehen?

Es fällt mir schwer, ein Beispiel zu finden, das unbedingt die aktuelle Semantik von erfordertval innerhalb von Konstruktoren und wäre nicht leicht mit einem richtigen, lexikalischen implementierbarval, möglicherweise in Kombination mitlazy.

Wie würde man dieses Verhalten umgehen?val, um alle Garantien zurückzuerhalten, die man von anderen Methoden gewohnt ist?

Man könnte vermutlich jede Instanz deklarierenvals zu seinlazy um zurück zu aval unveränderlich zu sein und das gleiche Ergebnis zu erzielen, egal wie auf sie zugegriffen wird, und den Effekt der Kompilierungszeit, wie er mit regulären Methoden beobachtet wird, weniger relevant zu machen, aber das scheint mir für so etwas ein schrecklicher Hack zu sein.

Angesichts der Tatsache, dass sich dieses Verhalten in der aktuellen Sprache wahrscheinlich nicht ändern wird, ist ein Compiler-Plug-in der richtige Ort, um dieses Problem zu beheben, oder ist es möglich, ein zu implementierenval-ähnliches Schlüsselwort für jemanden, der gerade eine Stunde damit verbracht hat, ein Problem zu beheben, das durch diese Kuriosität verursacht wurde, eine vernünftigere Semantik innerhalb der Sprache?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage