先ほど、SO postで、スレッドセーフで不変なコレクションをラップするコンテナクラスを作成するための慣用方法について質問しました。私が受け取った回答は、私が望むものではない様々な読み書きロックや同期を使っていました。不変のコレクションをScalaでラップしないようにするには?
私は別の質問をします。不変のコンテナをラップする次のクラスを不変にするにはどうすればよいですか? ...
class MyContainer[A] {
// method that returns a new MyContainer that includes the additional thing...
def add(thing: A): MyContainer[A] = {
???
}
def filter(p: A => Boolean): Option[Iterable[A]] = {
val filteredThings = backingStore.values.filter(p)
if (filteredThings.isEmpty) None else Some(filteredThings)
}
// method that returns a new MyContainer that does not include the thing with given uuid
def remove(uuid: UUID): MyContainer[A] = {
???
}
@ volatile private[this] var backingStore = immutable.HashMap.empty[UUID, A]
}
思考方法はadd
/remove
適宜変更新しいMyContainer
クラスのインスタンスを返す必要があるが、私は非常にそれを行う方法を見ることができませんか?
EDIT:コメントに反応しては、一つの可能な解決策は
class MyContainer[A](val backingStore: immutable.HashMap[UUID, A]) {
def add(thing: A): MyContainer[A] = {
new MyContainer(backingStore + (thing.uuid -> thing))
}
def filter(p: A => Boolean): Option[Iterable[A]] = {
val filteredThings = backingStore.values.filter(p)
if (filteredThings.isEmpty) None else Some(filteredThings)
}
def remove(uuid: UUID): MyContainer[A] = {
new MyContainer(backingStore - uuid)
}
}
...
backingStore
はもはやプライベートで...次のように何かないだろう(ただし、コンストラクタで
private
を置くことができます)。その他の考え?
'backingStore'を' @volatile var'ではなく 'val'にして、それがどこから来るのかを見てみましょう。(編集:typo) –
' backingStore'自体を非公開にします'val'を単に削除する(または明示的に' private val'を書く)ことができます。興味深い! –