9

我不小心遇到了这样的情况(示例被简化以隔离问题):

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 脚本运行时(相同的代码、减号object Maindef 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

编辑: 我找到了解决我的主要问题的方法:

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

这似乎在编译版本中工作(但不是作为 Scala 脚本!)。谁能解释一下这里发生了什么?

EDIT2:这作为一个脚本工作(同样的事情,只是使用defs):

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

1 回答 1

10

通常的方式是这样的(更改了嵌套,因此您可以将其粘贴到 REPL 中):

object Main{
  abstract class Element(other0: => Element) {
    lazy val other = other0
  }

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

  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)
  }
}

也就是说,取一个别名参数并将其粘贴到惰性 val 中以供将来参考。


编辑:您找到的修复程序有效,因为对象本身是惰性的,您可以引用它们,但在您使用它们之前不会创建它们。因此,一个对象可以自由地将自己指向另一个对象,而无需另一个对象已经被初始化。

于 2011-02-12T13:35:09.060 回答