在读取akka文档的消息和不变性部分下,它提到了"明确暴露状态"内部案例类。所以我的问题是;
说案例类"明确公开状态"是什么意思?
为了实现不变性,不足以为班级编写"案例"吗?还是我应该谨慎使用它?
说案例类"明确公开状态"是什么意思?
下面的参与者用可变的Set[Int]
表示其状态,该状态使用值1
,2
和3
初始化。
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
本身的边界之外变化。为了制作这种具体,假设AnotherActor
将GetState
消息发送给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
的行为更改(hashCode
,equals
等),从而破坏任何依赖那些一致的东西。m
对应于Broken
的内部(可变)状态,并将其暴露允许Broken
被突变。
我想您是指此特定的引用:
Scala案例类是不变的(如果您不明确暴露 状态)
以最简单的形式,案例类构造函数的参数将映射到" val"字段,因此它们的参考将是不可变的。但是,如果该字段本身是可变的(例如,引用可变的集合或对象)和,您可以公开(通过访问者方法,说),则该类将变得可变(因为您已经暴露了一个可变的可变的场地)。但是,如果您愿意,您仍然可以内部更改国家。