2

他のオブジェクトへのscala.ref.WeakReferenceを保持するcaseクラスをscalaで記述したいと思います。それがscalaで行われるためのベストプラクティスは何だろうか。

私はそれについていくつか考えました、そして最初のものはこれでした:

case class CC1(ref: Any) {
    private val weakRef: WeakReference[Any] = WeakReference(ref)

    def get: Any = weakRef()
}

しかし、scalaはCC1で、強力な参照を保持するrefのvalを自動的に生成するため、これは単純に機能しません。

私の2番目の考えは:

case class CC2(private val weakRef: WeakReference[Any]) {
    def get: Any = weakRef() 
}

それはうまくいきました。ただし、コードの再利用という点ではあまり友好的ではありません。weakRefgetが次のような基本クラス/トレイトから取得された場合はどうなりますか。

trait T3 {
    protected var weakRef: WeakReference[Any] = null

    def get: Any = if(weakRef != null) weakRef() else null
}

case class CC3(/* how should I initialize weakRef in T3 */) extends T3 {
}

どのようにコードを書きますか?何を提案しますか?前もって感謝します!

4

2 に答える 2

2

ケースクラスで弱い参照が必要な理由はわかりませんが、おそらく値を取得できるようにしたい、またはそれ以外の場合は実際に弱いことを透過的にしたい-そうでない場合は、WeakReferenceケースクラスで。まず、便利なラッパーを作成しましょう。

class Weakly[A](wr: java.lang.ref.WeakReference[A]) {
  def apply() = wr.get
  def get = Option(wr.get)
  def weak = wr
  override def hashCode = { val a = wr.get; if (a==null) wr.hashCode else a.hashCode }
  override def equals(a: Any) = a==wr.get
  override def toString = "~"+wr.get
}
object Weakly {
  def apply[A](a: A) = new Weakly(new java.lang.ref.WeakReference(a))
  def unapply[A](wa: Weakly[A]) = Option(wa())
}
implicit def strengthen_on_demand[A](w: Weakly[A]) = w()
implicit def weaken_on_demand[A](a: A) = Weakly(a)

hashCodeこれで、元のとequalsが表示され、元の文字列が前に表示されるという利点があります~(もちろん、これは変更できます)。最も重要なのは、参照に対してパターン マッチングを実行できることです (参照が存在する場合にのみ一致します)。これにより、最小限の余分な手間でケースクラスで弱い参照を作成できるようになりました。

scala> case class CC1(s: Weakly[String]) {}
defined class CC1

scala> val cc = CC1("fish")
cc: CC1 = CC1(~fish)

scala> cc match { case CC1( Weakly(s) ) => s; case _ => "(nope)" }
res0: String = fish

scala> val s: String = cc.s
s: String = fish

scala> cc.s.weak.clear

scala> cc match { case CC1( Weakly(s) ) => s; case _ => "(nope)" }
res2: String = (nope)
于 2012-10-20T15:36:02.637 に答える