对象被“随意”变为空

时间:2011-04-09 23:54:35

标签: scala

嘿伙计们, 我正在scala的项目工作,我遇到了非常奇怪的问题。这是代码的一部分:

class Entity(val id:String){
  override def toString = id
}

class RequirementType
case class DependsEither(t:List[(Entity,Int)]) extends RequirementType
case class Depends(t:(Entity,Int)) extends RequirementType

class BuildableEntity(override val id:String,
               val mineralCost:Int,
               val gasCost:Int,
               val buildTime:Int,
               val buildCount:Int,
               val supplyCount:Int,
               val req:List[RequirementType],
               val onBuildStart: GameState => GameState,       
               val onBuildFinish: GameState => GameState
            )extends Entity(id)

class SimpleBuilding(id:String,
       mineralCost:Int,
       gasCost:Int,
       buildTime:Int,
       req:List[RequirementType]
) extends BuildableEntity(id,mineralCost,gasCost,buildTime,1,0,req:::List(ConsumesOnStart((Drone,1))),{s=>s},{x=>x})
object SpawningPool extends SimpleBuilding("spawningPool",200,0,65,List(DependsEither(List((Hatchery,1),(Lair,1),(Hive,1)))))
object Lair extends SimpleBuilding("lair",150,100,80,List(ConsumesOnFinish(Hatchery,1),Depends(SpawningPool,1)))
object InfestationPit extends SimpleBuilding("infestationPit",100,100,50,List(DependsEither(List((Lair,1),(Hive,1)))))

现在,当我调用println(Lair.req)时,它有时会打印为

  

列表(ConsumesOnFinish((孵化场,1)),取决于((null,2)),ConsumesOnStart((无人机,1)))

有时候是

  

列表(ConsumesOnFinish((孵化,1)),   取决于((spawningPool,2)),ConsumesOnStart((无人机,1)))

如果有人知道可能出现什么问题,我会永远爱你。我不知道为什么它会这样做。我有更多的SimpleBuilding扩展,但它们似乎正常工作

编辑: 我还要提一下,编译后结果会发生变化。我的意思是,当我运行单元测试时,它有时会显示为null,有时也会显示为正确的实例。

3 个答案:

答案 0 :(得分:3)

Lair在其构造函数中使用SpawningPool并相互提升。但那时,另一个不存在。

答案 1 :(得分:3)

你在构造函数中有递归定义,虽然我相信它是支持的,但它看起来像是出了问题。你可以试试懒惰的vals,看看问题是否消失了?也就是说,

object X extends C("this",that,1) { /* code */ }

变为

lazy val X = new C("this",that,1) { /* code */ }

答案 2 :(得分:3)

这确实是循环依赖和初始化的情况。以下是您问题的简短版本:

class X(val x: List[X])
object A extends X(List(B))
object B extends X(List(A))

object Main {
  def main(args:Array[String]) {
    println("A.x: " + A.x)
    println("B.x: " + B.x)
  }
}

这将打印出来:

$ scala -cp classes Main
A.x: List(B$@143c8b3)
B.x: List(null)

您可以使用names参数来允许在使用对象之前完成对象构建:

class X(x0: => List[X]) {
  lazy val x = x0
}
object A extends X(List(B))
object B extends X(List(A))

修复程序适用于小测试用例:

$ scala -cp classes Main
A.x: List(B$@1feca64)
B.x: List(A$@6d084b)

根据此情况,您可能希望将req:List[RequirementType]更改为req0: => List[RequirementType]并添加lazy val req = req0

如果这对你有用,我们应该重新提出问题,提到对象初始化和循环依赖。请注意,这与this question/answer非常相似。