Zakres wartości instancji Scala
Zauważ, że to pytanie i podobne zostały zadane wcześniej, na przykład wPrześlij dalej referencje - dlaczego ten kod się kompiluje?, ale znalazłem odpowiedzi, aby nadal pozostawić kilka pytań otwartych, więc mam kolejną kwestię.
W ramach metod i funkcji efektval
słowo kluczowe wydaje się leksykalne, tj.
def foo {
println(bar)
val bar = 42
}
wydajność
error: forward reference extends over definition of value bar
Jednak w ramach klas zasady ustalania zakresuval
wydaje się zmieniać:
object Foo {
def foo = bar
println(bar)
val bar = 42
}
Nie tylko kompiluje, ale takżeprintln
w konstruktorze da0
jako wyjście, podczas wywoływaniafoo
po pełnym skonstruowaniu instancji spowoduje oczekiwaną wartość42
.
Wydaje się więc możliwe, że metody przekazywania wartości instancji referencyjnych, które zostaną ostatecznie zainicjalizowane przed wywołaniem metody (chyba że oczywiście wywołujesz ją z konstruktora), oraz dla instrukcji w konstruktorze przekazywać wartości referencyjne w ten sam sposób, uzyskując do nich dostęp przed ich zainicjowaniem, co skutkuje głupią dowolną wartością.
Z tego wynika kilka pytań:
Dlaczegoval
wykorzystywać leksykalny efekt kompilacji w konstruktorach?Biorąc pod uwagę, że konstruktor jest tak naprawdę tylko metodą, wydaje się to raczej niespójne, aby całkowicie upuścićval
efekt kompilacji, nadając mu zwykły efekt tylko w czasie wykonywania.
val
, skutecznie, utracić efekt deklarowanianiezmienny wartość?Dostęp do wartości w różnym czasie może skutkować różnymi wynikami. Dla mnie wygląda na to, że wyciekł szczegół implementacji kompilatora.
Jak mogą wyglądać uzasadnione przypadki użycia?Trudno mi wymyślić przykład, który absolutnie wymaga aktualnej semantykival
w konstruktorach i nie da się łatwo zaimplementować za pomocą właściwego, leksykalnegoval
, ewentualnie w połączeniu zlazy
.
val
, odzyskując wszystkie gwarancje, których przyzwyczaiłeś się do używania go w ramach innych metod?Można przypuszczalnie ogłosić wszystkie przypadkival
byćlazy
aby wrócić doval
bycie niezmiennym i uzyskiwanie tego samego rezultatu bez względu na to, w jaki sposób są one dostępne i aby efekt kompilacji obserwowany w zwykłych metodach był mniej istotny, ale wydaje się to dość okropnym hackiem dla tego rodzaju rzeczy.
Biorąc pod uwagę, że to zachowanie prawdopodobnie nigdy nie zmieni się w rzeczywistym języku, czy wtyczka kompilatora byłaby właściwym miejscem do rozwiązania tego problemu, czy może zaimplementowaćval
-alike keyword with, dla kogoś, kto spędził godzinę na debugowaniu problemu spowodowanego przez tę dziwaczność, bardziej sensownej semantyki w języku?