具有可变伙伴的不变POD类

时间:2018-08-02 14:05:22

标签: scala akka

我发现自己遇到了容易出错的代码;模式是这样的:

final class StateVars(val x:Int, val y:Int)

final class StateVarsMutable(var x:Int, var y:Int) {
  // req. case classes & >1 element w/ same ordering
  // - can also do similar with shapeless
  // def snapshot():StateVars = StateVars.tupled( 
  //  StateVarsMutable.unapply(this).get )
  def snapshot() = new StateVars(x, y) // generic
}

在上面的实例中,StateVarsMutable可能包含在Actor中,但是Actor有时可能会通过StateVars发送其状态的快照。似乎可以使用kailuowang's henkan。在不影响运行时性能的情况下,是否存在针对这种情况的最佳或通用方法?

1 个答案:

答案 0 :(得分:0)

不可变类的可变性

问题中描述的模式是不必要的。

case class in scala通过使用persistent data structure模式解决了该问题试图解决的问题。

修改问题的类声明以包含“ case”:

final case class StateVars(x: Int, y: Int)

现在可以通过返回代表新状态的新对象来“突变”此状态:

val initialState = StateVars(0,0)

//Increment x while keeping y the same
val incrementX : StateVars = initialState copy (x = initialState.x + 1)

//Increment y while keeping x the same
val incrementY : StateVars = initialState copy (y = initialState.y + 1)

如果您需要持续维护“快照”,请使用var

var snapshot : StateVars = StateVars(0,0)

snapshot = snapshot copy (x = snapshot.x + 1, y = snapshot.y +1)

演员内部

可以使用Actor编写一个var来维护“快照”,以允许更改值:

object StateVarsRequest

class StateVarsActor(initialStateVars : StateVars) extends Actor {

  private var snapshot : StateVars = initialStateVars

  override def receive : Receive = {
    case stateVars : StateVars => snapshot = stateVars
    case _ : StateVarsRequest  => sender ! snapshot
  }
}

snapshot可以看作是指向不可变类的指针。当请求者在消息中收到快照时,他们不是在获取可变指针,而是在获取不可变数据。

因此,如果快照在请求者收到其数据后发生更改,则该请求者的数据不会更改。