如何以更具功能性的风格重写带有变量字段的Scala类?

oprakyz7  于 2022-11-29  发布在  Scala
关注(0)|答案(2)|浏览(86)
class MyClass {

  var myField = List.empty[Double]
  var mySecondField = List.empty[Double]

  def myMethod = {
     // code does some heavy computation
     myField = myComputationOutput
     mySecondField = mySecondComputationOutput
  }
}

我希望避免在MyClass中保存状态,但是在myMethod调用期间存储计算值似乎很方便。
有哪些设计备选方案?

az31mfrm

az31mfrm1#

如果要缓存这些繁重计算的结果,则使用memoize pattern。如果参数相同,则第一次计算结果并返回:

class MyClass {
  var myField = Option[List[Double]] = None
  var mySecondField = Option[List[Double]] = None

  def myMethod = {
    if ( ! myField.isDefined ) {
      myField = Some(myComputationOutput)
    }
    if ( ! mySecondField.isDefined ) {
      mySecondField = Some(mySecondComputationOutput)
    }
  }
}

如果这些值从未更改,则可以考虑使用延迟求值,仅在第一次引用它们时计算它们:

class MyClass {
  lazy val myField = myComputationOutput
  lazy val mySecondField = mySecondComputationOutput
}

另一种方法是考虑MyClass实际上是两个类,对应于两个阶段,即计算完成之前和之后,那么,可变性是全局状态,而不是两个变量状态的混合。

lymnna71

lymnna712#

您可以返回MyClass的新示例,而不是在myMethod中返回Unit
使用case类的代码:

case class MyClass(myField: List[Double] = List.empty) {
   def myMethod = copy(myField = myComputationOutput)
}

或者甚至更好:

val myClass = MyClass(fields)
myClass.copy(myField = myComputationOutput)

这样你就不需要myMethod了。

相关问题