在阅读akka docs正确的消息和不变性部分,它提到了“明确暴露状态”内的案例类。所以我的问题是;斯卡拉案例类“明确暴露状态”
什么意思是说“明确暴露状态”案例类?
为了实现不可变性,是不是足够写一个类的“案例”? 或者我应该小心使用它?
在阅读akka docs正确的消息和不变性部分,它提到了“明确暴露状态”内的案例类。所以我的问题是;斯卡拉案例类“明确暴露状态”
什么意思是说“明确暴露状态”案例类?
为了实现不可变性,是不是足够写一个类的“案例”? 或者我应该小心使用它?
什么意思是说“明确暴露状态”案例分类?
下面的演员表示它与一个可变的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类时,请确保所有类的参数本身都是不可变的。
或者我应该小心使用它?
是。
我认为它指的是做这样的事情
case class Broken(m: mutable.Map[String, String])
Broken
是表面上不变的,因为没有它的字段都可以直接设置到任何东西,但它仍然可以通过更新m
,这将导致改变包含Broken
的行为改变(hashCode
,equals
等),从而破坏任何依赖于那些一致的东西。 m
对应于Broken
的内部(可变)状态,并且暴露它也允许Broken
也被突变。
我相信你指的是这个特殊的报价:
Scala的case类,它是不变(如果你不明确暴露 的状态)
在最简单的形式,一个case类构造函数的参数将被映射到'val'字段,因此它们的引用将是不可变的。然而,如果该字段本身是可变的(例如引用可变集合或对象)和你公开(通过访问器方法),那么该类将变得可变(因为你暴露了一个可变字段)。不过,如果你愿意,你仍然可以在内部改变状态。