2017-09-15 63 views
1

在阅读akka docs正确的消息和不变性部分,它提到了“明确暴露状态”内的案例类。所以我的问题是;斯卡拉案例类“明确暴露状态”

什么意思是说“明确暴露状态”案例类?

为了实现不可变性,是不是足够写一个类的“案例”? 或者我应该小心使用它?

回答

3

什么意思是说“明确暴露状态”案例分类?

下面的演员表示它与一个可变的Set[Int]状态,这是与值12初始化,并且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类时,请确保所有类的参数本身都是不可变的。

或者我应该小心使用它?

是。

3

我认为它指的是做这样的事情

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

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

0

我相信你指的是这个特殊的报价:

Scala的case类,它是不变(如果你不明确暴露 的状态)

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