私は誤って次のような状況に遭遇しました (例は問題を特定するために単純化されています)。
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
出力は一種の理にかなっています。どうやら Second オブジェクトが作成された時点では、First オブジェクトがまだ存在しないため、null
割り当てられます。問題は... それはとても間違っている !これを追跡するのに数時間かかりました。コンパイラはこれについて何かを伝えるべきではありませんか? 興味深いことに、これを Scala スクリプト (同じコード、マイナスobject 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)
...
実行時に少なくとも同じくらい有益なものを取得したいと思います...
Ok。私は私の暴言を終えました。今、私は何かを尋ねるべきだと思います。:) では、お互いを指しているケースオブジェクトの素敵なデザインをお勧めできますか? ちなみに、私の実際の状況では、次のインスタンスと前のインスタンスを循環的に指すオブジェクトがいくつかあります (最後のインスタンスは最初のインスタンスを指し、その逆も同様です)。
Scala 2.8.1-final の使用
編集: 私は私の主な問題の解決策を見つけました:
abstract class Element {
val other: Element
}
case object First extends Element {
val other = Second
}
case object Second extends Element {
val other = First
}
これはコンパイルされたバージョンで動作するようです (ただし、Scala スクリプトとしては動作しません!)。ここで何が起こっているのか、誰かに光を当てることができますか?
EDIT2:これはスクリプトとして機能します(sを使用するだけで同じことですdef
):
abstract class Element { def other: Element }
case object First extends Element { def other = Second }
case object Second extends Element { def other = First }