2017-09-15 3 views
1

メッセージと不変性のセクションの下にあるakka docsを読んでいる間、それはケースクラスの中の "明示的に状態を公開する"ことについて言及しています。だから私の質問は、"状態を明示的に公開する"スカラの場合のクラス

ケースクラスの「状態を明示的に公開する」とはどういう意味ですか?

不変性を達成するために、クラスに「ケース」を書くだけでは不十分ですか? またはその使用法に注意する必要がありますか?原因となる、そのフィールドのいずれも直接何にも設定することはできませんので、私はそれが

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

Brokenのようなものをやってを参照すると信じて

答えて

3

「明示的に状態を公開する」とは、ケースクラスのことですか?

以下アクターは、値1で初期化されている可変Set[Int]、との状態を表し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の境界の外側で変更可能になります。具体的には、AnotherActorMyActorGetStateメッセージを送信したとします。このとき、MyActorAnotherActorに状態を送信します。その状態は、ケースクラス内に送達されても、

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をラップすることができますが、それはですこの場合は必須ではありません)。

不変性を達成するために、クラスに「ケース」を書くだけでは不十分ですか?

いいえアクターメッセージングのケースクラスを使用する場合は、クラスのすべてのパラメータ自体が不変であることを確認してください。

また、その使用方法に注意する必要がありますか?

はい。

3

は、表面的に不変であるが、それはまだmを更新することで変更することができます(hashCodeequalsなど)を変更して、一貫性のあるものに依存するものをすべて破棄することを意味します。 mBrokenの内部(変更可能な)状態に対応し、それを公開することでBrokenも変異させることができます。その最も単純な形式で

(明示的 状態を公開していない場合)、不変である

Scalaのケースクラスを:

0

は、私はあなたがこの特定の引用を参照していると推定しますcaseクラスのコンストラクタのパラメータは 'val'フィールドにマップされるため、その参照は不変です。しかし、フィールド自身が可変である場合(例えば、可変コレクションまたはオブジェクトを参照する場合)、を公開すると、(可変長フィールドを公開しているので)クラスが変更可能になります。しかし、あなたが望むなら、あなたは内部的に状態を変えることはできません。

関連する問題