Выполнение работы val lazy, поскольку оно перемещает точку, в которой 0.02 записывается в поле. Чтобы понять, что происходит, прочитайте следующий код, который представляет собой java-байтовые коды, которые производит scalac для вашего примера.
Следует отметить, что поля a и b сохраняются на дочернем объекте и что их значения 0.02 и 0.2 не записываются до тех пор, пока не вызывается конструктор родителя. Однако println вызывается в конструкторе родителя, прежде чем поля будут записаны. Таким образом, ваша проблема.
Выполнение работы vals lazy, поскольку в момент вызова a() или b() будет вызываться код инициализации .. то есть родительский класс теперь будет вызывать код в дочернем классе для установки полей на класс ребенка.
public abstract class Function implements scala.ScalaObject {
public abstract double a();
public abstract double b();
public Function(); // NB: calls a() and b() on the child class
Code:
0: aload_0
1: invokespecial #13 // Method java/lang/Object."<init>":()V
4: getstatic #19 // Field scala/Predef$.MODULE$:Lscala/Predef$;
7: new #21 // class scala/Tuple2$mcDD$sp
10: dup
11: aload_0
12: invokevirtual #25 // Method a:()D
15: aload_0
16: invokevirtual #27 // Method b:()D
19: invokespecial #30 // Method scala/Tuple2$mcDD$sp."<init>":(DD)V
22: invokevirtual #34 // Method scala/Predef$.println:(Ljava/lang/Object;)V
25: return
}
public class ChildFunction extends Function implements scala.ScalaObject {
public double a();
Code:
0: aload_0
1: getfield #12 // Field a:D
4: dreturn
public double b();
Code:
0: aload_0
1: getfield #14 // Field b:D
4: dreturn
public ChildFunction(); // NB invokes parent constructor BEFORE writing values to fields a and b.
Code:
0: aload_0
1: invokespecial #20 // Method Function."<init>":()V
4: aload_0
5: ldc2_w #21 // double 0.02d
8: putfield #12 // Field a:D
11: aload_0
12: ldc2_w #23 // double 0.2d
15: putfield #14 // Field b:D
18: return
}
Вы можете исправить эту проблему, используя defs вместо lazy val (пример ниже). Или еще лучше, удалите println и только вызовите a() и b() после ChildFunction был полностью построен.
object StackOverflowTest extends App
{
new ChildFunction()
}
abstract class Function() {
def a: Double
def b: Double
println(a, b)
}
class ChildFunction() extends Function() {
override def a = 0.02
override def b = 0.2
}
Это поможет нам, если ваш пример будет завершен, чтобы мы могли его запустить. Что такое терминал и нейрональная функция, они даже необходимы для целей воспроизведения проблемы? –
@ChrisK Вы абсолютно правы. Я очистил пример. – Andrey