用于创建两个相互依赖的对象的scala模式是否可以更干净地实现?

时间:2012-08-06 10:40:44

标签: scala refactoring

假设我有两个数据结构,它们都希望引用另一个。 我不能简单地让每个人成为一个懒惰的人,并将他们传递给对方;发生堆栈溢出。

我提出的解决方案是:

class Alpha((deferredBeta: Alpha) => Beta) {
   lazy val beta = deferredBeta(this)
}

class Beta(val alpha: Alpha) {}

def main {
   val alpha = Alpha(beta)
   val beta = (alpha: Alpha) => Beta(alpha)
}

虽然它有效但似乎有点脆弱,特别是在进行子类化时。此外,如果没有良好的文档,那么目前所做的并不明显。

这个问题是否有更清洁的解决方案?

2 个答案:

答案 0 :(得分:3)

我认为这个解决方案最简单:

class Alpha(_beta: => Beta) {
  lazy val beta = _beta
}

class Beta(_alpha: => Alpha) {
  lazy val alpha = _alpha
}

// Exiting paste mode, now interpreting.

defined class Alpha
defined class Beta

scala> lazy val (alpha: Alpha, beta: Beta) = (new Alpha(beta), new Beta(alpha))
alpha: Alpha = <lazy>
beta: Beta = <lazy>

scala> alpha.beta
res2: Beta = Beta@4a40050

scala> beta.alpha
res3: Alpha = Alpha@38f18cc3

您还可以为alpha beta对添加工厂:

object AlphaBeta {
  def apply() = {
    lazy val tuple @ (alpha: Alpha, beta: Beta) = (new Alpha(beta), new Beta(alpha))
    tuple
  }
}

scala> AlphaBeta()
res13: (Alpha, Beta) = (Alpha@2a3fa87a,Beta@394df741)

答案 1 :(得分:1)

不完全是你要求的,但它有效:

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Alpha {
  self: Beta =>
  val beta: Beta = self
}

trait Beta {
  self: Alpha =>
  val alpha: Alpha = self
}

// Exiting paste mode, now interpreting.

defined trait Alpha
defined trait Beta

scala> val (alpha, beta) = {
     |   val ab = new Alpha with Beta
     |   (ab: Alpha, ab: Beta)
     | }
alpha: Alpha = $anon$1@13668e0b
beta: Beta = $anon$1@13668e0b

scala> alpha.beta
res0: Beta = $anon$1@13668e0b