I understand the general use of Lazy vals to get around initialization order problems in scala, but something has always bothered me about this explanation. If a "Lazy Val" is initialized during it's first access, and the parent constructor is making use of it BEFORE it could possibly exist - what exactly is going on here? In the below example, when "println("A: " + x1)" is called - Class B doesn't exist yet.. but the value does correctly print. At the exact moment we see "A: Hello" - did this happen in the constructor of A, or delayed somehow until B fully existed? In a sense, marking it "Lazy" has counter-intuitively made it available ahead of schedule?
Thank you
(referenced from https://github.com/paulp/scala-faq/wiki/Initialization-Order)
abstract class A {
val x1: String
println("A: " + x1)
}
class B extends A {
lazy val x1: String = "hello"
}
The object itself doesn't exist, but fields within the object can exist and be calculated.
What's happening is that from within A's constructor, it's accessing x1 and therefore forcing the lazy value to be computed. The reason A can know it needs to call B's x1 method, is because it's dynamically dispatched (just like in Java).
If it helps, the stack would be something similar to this:
B.x1$lzycompute
B.x1
A.<init>
B.<init>
If it helps, here is a rough version of your code in Java:
public class Testing {
public static void main(String[] args) {
new B();
}
public static abstract class A {
public abstract String x1();
public A() {
System.out.println(x1());
}
}
public static class B extends A {
private boolean inited = false;
private String x1;
private String computeX1() {
x1 = "hello";
inited = true;
return x1;
}
public String x1() {
return this.inited ? x1 : computeX1();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With