Scala案例类"明确暴露国家"

时间:2017-09-15 16:32:17

标签: scala akka immutability case-class

在消息和不变性部分正确阅读akka docs时,它提到"明确暴露国家"内部案例类。所以我的问题是;

谚语"明确暴露国家"是什么意思?案例类?

为了实现不变性,还不足以写出" case"一堂课? 或者我应该小心它的用法?

3 个答案:

答案 0 :(得分:3)

我认为它指的是做类似

的事情
case class Broken(m: mutable.Map[String, String])

Broken表面上是不可变的,因为它的所有字段都不能直接设置为任何字段,但它仍然可以通过更新m来更改,这将导致包含Broken的行为改变(hashCodeequals等),从而打破任何依赖于那些一致的东西。 m对应于Broken的内部(可变)状态,并且公开它也允许Broken进行变异。

答案 1 :(得分:3)

  

对于案例类,“明确暴露国家”是什么意思?

下面的演员用可变Set[Int]表示其状态,该状态使用值123初始化:

case class State(s: mutable.Set[Int])

case class Add(num: Int)
case class Remove(num: Int)

class MyActor extends Actor {
  val state = mutable.Set(1, 2, 3)

  def receive = {
    case GetState =>
      sender ! State(state)
    case Add(i) =>
      state += i
    case Remove(i) =>
      state -= i
  }
}

当此actor收到GetState消息时,它将其状态包装在State case类中,并将其发送给发送方。尽管State案例类是不可变的,但其参数s是可变的Set。因此,当MyActor创建具有其状态的State实例并将其作为消息发送给GetState消息的发件人时,MyActor的状态将变为可修改的MyActor本身的边界。为了具体说明,我们要说AnotherActorGetState发送MyActor条消息,此时MyActor将其状态发送到AnotherActor。这是后者:

class AnotherActor extends Actor {
  def receive =>
    case State(state) =>
      // MyActor's state is exposed here
      state -= 2
}

AnotherActor通过删除MyActor来修改2的状态,即使该状态是在案例类中传递的。

为了缓解这种泄漏,限制对actor本身的可变性。在此示例中,不是使用val state = mutable.Set(1, 2, 3),而是定义var state = immutable.Set(1, 2, 3)

class MyActor extends Actor {
  var state = immutable.Set(1, 2, 3)

  def receive = {
    case GetState =>
      sender ! state
    case Add(i) =>
      state = state + i
    case Remove(i) =>
      state = state - i
  }
}

在这里,MyActor可以安全地将其状态作为消息发送,因为它是一个不可变的Set(我们可以将Set包装在一个案例类中,但在这种情况下这不是必需的)

  

为了实现不变性,为一个班级写“案例”是不够的?

没有。使用case类进行actor消息传递时,请确保所有类的参数本身都是不可变的。

  

或者我应该注意它的用法?

答案 2 :(得分:0)

我认为你引用了这个特别的引用:

  

Scala案例类是不可变的(如果没有显式公开)   国家)

在最简单的形式中,案例类构造函数的参数将映射到' val'字段因此它们的引用将是不可变的。但是,如果字段本身是可变的(例如引用可变集合或对象),那么(通过访问器方法,例如),那么该类将变得可变(因为您已经暴露了)一个可变的领域)。但是,如果你愿意的话,并不是说你仍然可以在内部改变状态。