2

我想在 scala 中编写一个案例类,其中包含对其他对象的 scala.ref.WeakReference。我想知道在 scala 中完成的最佳实践是什么。

我对此有一些想法,第一个是这样的:

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

    def get: Any = weakRef()
}

但这根本行不通,因为 scala 会在 CC1 中自动为 ref 生成一个具有强引用的 val。

我的第二个想法是:

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

这有什么问题?

case class CC3(private val wr:WeakReference[AnyRef]) extends T3 {
  weakRef = wr  
}

如果您想避免引入另一个字段,您可以更改 trait 使其不包含字段,而仅包含 getter 和 setter 方法。

trait T3 {
  protected def weakRef: WeakReference[AnyRef]
  protected def weakRef_=(wr:WeakReference[AnyRef])

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

然后你在你的案例类中实现这些方法。

case class CC3(private var wr:WeakReference[AnyRef]) extends T3 {
  override protected def weakRef = wr
  override protected def weakRef_=(w:WeakReference[AnyRef]) { wr = w }
}
于 2012-10-20T14:44:58.027 回答
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)

现在我们包装的弱引用被包装了两次,其优点是它显示了它的原始hashCodeequals,它显示了~前面的原始字符串(你当然可以改变它),最重要的是你可以对引用进行模式匹配(只有当引用存在时才会匹配)。有了这个,我们现在可以在案例类中进行弱引用,而无需额外的麻烦:

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 回答