Różnica między nimi polega na tym, że val
jest wykonywany, gdy jest zdefiniowany, podczas gdy lazy val
jest wykonywany, gdy uzyskuje się do niego dostęp po raz pierwszy.
scala> val x = { println("x"); 15 }
x
x: Int = 15
scala> lazy val y = { println("y"); 13 }
y: Int = <lazy>
scala> x
res2: Int = 15
scala> y
y
res3: Int = 13
scala> y
res4: Int = 13
W przeciwieństwie do metody (zdefiniowanego z def
) A lazy val
jest wykonywany raz i nigdy więcej. Może to być przydatne, gdy operacja zajmuje dużo czasu i kiedy nie ma pewności, czy jest ona później używana.
scala> class X { val x = { Thread.sleep(2000); 15 } }
defined class X
scala> class Y { lazy val y = { Thread.sleep(2000); 13 } }
defined class Y
scala> new X
res5: X = [email protected] // we have to wait two seconds to the result
scala> new Y
res6: Y = [email protected] // this appears immediately
Tutaj, gdy wartości x
i y
nigdy nie są wykorzystywane jedynie x
niepotrzebnego marnowania zasobów. Jeśli przyjmiemy, że y
nie ma skutków ubocznych i nie wiemy, jak często jest on dostępny (nigdy, raz, tysiące razy), nie ma sensu deklarować go jako def
, ponieważ nie chcemy go wykonywać kilka razy.
Aby uzyskać informacje na temat implementacji lazy vals
, patrz: question.
Jako uzupełnienie: @ViktorKlang opublikowane na Twitterze: ["mało znany fakt Scala: jeśli inicjalizacja leniwy val rzuca exce ption, spróbuje ponownie zainicjować wartość val przy następnym dostępie. "] (https://twitter.com/#!/viktorklang/status/104483846002704384) –