【问题标题】:Scala Using WeakReference in A Case ClassScala 在案例类中使用弱引用
【发布时间】:2012-10-20 14:19:33
【问题描述】:

我想在 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 {
}

您将如何编写代码?请问你有什么建议?提前致谢!

【问题讨论】:

    标签: scala weak-references case-class


    【解决方案1】:

    这是怎么回事?

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

    【讨论】:

    • 是的,它有效。我也应该想到的。但它引入了另一个持有弱引用的 val,在 scala 的精神下看起来不那么优雅。
    • 谢谢,金。也许这是 scala 代码冗长的场景之一。
    【解决方案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,它显示了前面带有~的原始字符串(当然你可以改变这个),并且最重要的是,您可以对参考进行模式匹配(仅当参考存在时才会匹配)。有了这个,我们现在可以在 case 类中进行弱引用,而不必大惊小怪:

    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)
    

    【讨论】:

    • 你是对的。我想让case类在内部存储一个weakref变得透明,但是在默认构造函数中将参数定义为WeakReference实际上没有达到这个目标。您的解决方案非常有趣,它大大简化了 WeakReference 的使用。
    猜你喜欢
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 2020-02-05
    • 2021-12-26
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多