斯卡拉案例类"explicitly exposing the state"



在读取akka文档的消息和不变性部分下,它提到了"明确暴露状态"内部案例类。所以我的问题是;

说案例类"明确公开状态"是什么意思?

为了实现不变性,不足以为班级编写"案例"吗?还是我应该谨慎使用它?

说案例类"明确公开状态"是什么意思?

下面的参与者用可变的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
  }
}

当该演员收到GetState消息时,它将其状态包裹在State案例类中,并将其发送给发件人。即使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通过从中删除2修改MyActor的状态,即使该状态在案例类中传递。

减轻这种泄漏,将可突变性限制为演员本身。在此示例中,代替具有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 class Broken(m: mutable.Map[String, String])

Broken在表面上是不变的,因为它的字段都无法直接设置为任何东西,但是它仍然可以通过更新m来更改,这会导致包含的Broken的行为更改(hashCodeequals等),从而破坏任何依赖那些一致的东西。m对应于Broken的内部(可变)状态,并将其暴露允许Broken被突变。

我想您是指此特定的引用:

Scala案例类是不变的(如果您不明确暴露 状态)

以最简单的形式,案例类构造函数的参数将映射到" val"字段,因此它们的参考将是不可变的。但是,如果该字段本身是可变的(例如,引用可变的集合或对象),您可以公开(通过访问者方法,说),则该类将变得可变(因为您已经暴露了一个可变的可变的场地)。但是,如果您愿意,您仍然可以内部更改国家。

相关内容

最新更新