1

2 つのデータ構造があり、両方が他方への参照を必要としているとします。単純にそれぞれを怠惰な val にして、それらを互いに渡すことはできません。スタック オーバーフローが発生します。

私が思いついた解決策は次のようなものです:

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

機能しますが、特にサブクラス化に関しては、少し壊れやすいようです。また、適切なドキュメントがないと、何が行われているのかわかりません。

この問題に対するよりクリーンな解決策はありますか?

4

2 に答える 2

3

I think this solution is the simplest:

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

You could also add a factory for an alpha beta pair:

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)
于 2012-08-06T11:11:57.930 に答える
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
于 2012-08-06T10:57:00.177 に答える