Определить рекурсивные ссылки - отложенный вызов вызывает переполнение стека

Для сценария потока данных мне нужны значения, которые рекурсивно ссылаются друг на друга. Следующее не работает:

class Foo(val that: Foo)

class Bar {
  lazy val a: Foo = new Foo(b)
  lazy val b: Foo = new Foo(a)
  println(s"a = $a, b = $b")
}

new Bar  // boom!

Как бы я решить это, не пачкая руки var?

2 ответа

Решение

Вам просто нужно больше ленивых!

class Foo(_that: => Foo){ lazy val that = _that }


class Bar {
  lazy val a: Foo = new Foo(b)
  lazy val b: Foo = new Foo(a)
  println(s"a = $a, b = $b")
}

val bar = new Bar

bar.b.that eq bar.a
// true

bar.b eq bar.a.that
// true

Вы можете использовать параметр по имени и другой lazy val:

class Foo(_that: => Foo) {
  lazy val that = _that
}

class Bar {
  lazy val a: Foo = new Foo(b)
  lazy val b: Foo = new Foo(a)
  println(s"a = $a, b = $b")
}

val bar = new Bar()
println(bar.a.that)

Параметр by name откладывает оценку ссылки на другой Foo, Как только вы получите доступ that, и то и другое Foos были созданы, так что вы в порядке.

Другие вопросы по тегам