scala: циклическая ссылка при создании объекта?

Я случайно столкнулся с такой ситуацией (пример упрощен, чтобы изолировать проблему):

abstract class Element(val other: Element)

case object First extends Element(Second)
case object Second extends Element(First)

object Main {
  def main(arguments: Array[String]) {
    val e1 = First
    val e2 = Second
    println("e1: "+e1+"   e1.other: "+e1.other)
    println("e2: "+e2+"   e2.other: "+e2.other)
  }
}

Кто-нибудь хочет угадать результат? : -)

e1: First   e1.other: Second
e2: Second   e2.other: null

Вывод имеет смысл. Очевидно, на момент создания Второго объекта Первый еще не существует, поэтому присваивается null . Проблема в том ... Это так неправильно! Мне потребовалось пару часов, чтобы разыскать этого. Не должен ли компилятор что-то сказать об этом? Интересно, что когда я попытался запустить это как скрипт Scala (тот же код, минус объект Main и def main ] строки и закрытие } s), У меня бесконечная последовательность (не совсем бесконечная - в какой-то момент список останавливается, я думаю, из-за некоторого ограничения на глубину трассировки исключений или чего-то еще) таких исключений:

vilius@blackone:~$ scala 1.scala
...
at Main$$anon$1.Main$$anon$$Second(1.scala:4)
at Main$$anon$1$First$.<init>(1.scala:3)
at Main$$anon$1.Main$$anon$$First(1.scala:3)
at Main$$anon$1$Second$.<init>(1.scala:4)
at Main$$anon$1.Main$$anon$$Second(1.scala:4)
at Main$$anon$1$First$.<init>(1.scala:3)
...

Я бы хотел получить что-нибудь хотя бы как информативное во время выполнения ...

Хорошо. Я закончил свою тираду. Теперь я думаю, мне следует кое-что спросить. :) Итак, не могли бы вы порекомендовать какой-нибудь красивый дизайн для объектов корпуса, указывающих друг на друга? Кстати, в моей реальной ситуации есть несколько объектов, указывающих на следующий и предыдущий экземпляры по кругу (последний указывает на первый и наоборот).

Использование Scala 2.8.1-final

EDIT : Я нашел решение своей основной проблемы:

abstract class Element {
  val other: Element
}
case object First extends Element {
  val other = Second
}
case object Second extends Element {
  val other = First
}

Кажется, это работает в скомпилированной версии (но не как скрипт Scala!). Может ли кто-нибудь пролить свет на то, что здесь происходит?

EDIT2: Это работает как сценарий (то же самое, только с использованием def s):

abstract class Element { def other: Element }
case object First extends Element { def other = Second }
case object Second extends Element { def other = First }
8
задан Vilius Normantas 12 February 2011 в 13:45
поделиться