Scala dziwne zachowanie w inicjalizacji klasy / obiektu [duplikat]
Możliwy duplikat:
Scala i referencje do przodu
Czy jest jakieś uzasadnienie, dlaczego w Scali działają następujące elementy:
Wersja 1object Strange extends App {
val x = 42
Console.println(x) // => outputs "42", as expected
}
Wersja 2object Strange extends App {
Console.println(x) // => "0" ?!
val x = 42
}
Dlaczego to robiskompilować w ogóle i dlaczego zachowuje się tak dziwnie bezkażdy ostrzeżenia czy cokolwiek?
To także ten sam problemclass
:
class StrangeClass {
Console.println(x) // => still "0"
val x = 42
}
object TestApp extends App {
new StrangeClass()
}
Nie ma takiego problemu z ciałem zwykłej metody:
def nonStrangeMethod {
Console.println(y) // => fails with "not found: value y", as expected
y = 42
}
A zachowanie zmienia się drastycznie, jeśli dodamy „końcowe” do deklaracji val:
class StrangeClass {
Console.println(x) // => "42", but at least that's expected
final val x = 42
}
Dla rekordów następujące Java statyczne (Scalaobject
) odpowiednik:
public class Strange {
static {
System.out.println(x);
}
static int x = 42;
public static void main(String[] args) {}
}
kompilacja kończy się niepowodzeniem ze zwykłym i zrozumiałym błędem „Nie można odwołać się do pola, zanim nie zostanie zdefiniowane” w linii # 3 i Java niestatyczna (class
) odpowiednik:
public class Strange {
Strange() {
System.out.println(x);
int x = 42;
}
public static void main(String[] args) {
new Strange();
}
}
oczywiście nie powiedzie się, gdy „x nie może być rozwiązany do zmiennej” w linii # 3.