可变的Scala集合的不可修改的视图

Chr*_*tin 10 scala scala-collections

我有一个私有字段的类,它是一个可变集合.ArrayBuffer虽然我的问题扩展到任何有限的,有序的随机访问集合类型,但这个特定实例中的字段是一个.我想暴露这个字段而不允许其他人修改它.在Java中我会添加一个方法,如:

private List<T> theList;

public List<T> getList() {
    return Collections.unmodifiableList(theList);
}
Run Code Online (Sandbox Code Playgroud)

在Java中,我们只接受结果是List没有完全实现List接口,因为#add和朋友一起抛出UnsupportedOperationException.

在Scala中,我希望找到与存取像适当的特质iterator,size以及apply(对于通过索引检索值),但没有改变者.这种类型是否存在,我还没有找到?

Mar*_*ila 9

Scala集合库面向不变性,不变性不仅仅指您不允许修改给定集合的事实,而且还保证您不会被任何人修改过该集合.

所以你不能,你不应该得到像immutable.Seq这样的集合作为Scala中可变缓冲区的视图,因为它打破了这种保证.

但你可以像这样简单地实现不可修改的可变Seq的概念:

class UnmodifiableSeq[A](buffer: mutable.Seq[A]) extends mutable.Seq[A]{
    def update(idx: Int, elem: A) {throw new UnsupportedOperationException()}

    def length = buffer.length

    def apply(idx: Int) = buffer(idx)

    def iterator = buffer.iterator
}
Run Code Online (Sandbox Code Playgroud)

用法:

val xs = Array(1, 2, 3, 4)
val view = new UnmodifiableSeq(xs)
println(view(2)) >> 3
view(2) = 10 >> Exception in thread "main" java.lang.UnsupportedOperationException
Run Code Online (Sandbox Code Playgroud)

编辑:

获取集合的不可修改视图的一种可能更好的方法是通过向下转换来collection.Seq提供无可变更新操作:

val xs = Array(1, 2, 3)
val view: Seq[Int] = xs //this is unmodifiable
Run Code Online (Sandbox Code Playgroud)

或创建一个包装器,Seq如果你有自己的自定义可变类,它将扩展.

class UnmodifiableView[A](col: MutableCollection[A]) extends collection.Seq[A]{
    def length = col.length

    def apply(idx: Int) = col(idx)

    def iterator = col.iterator
}
Run Code Online (Sandbox Code Playgroud)

scala.collection.Seq特征不保证不变性,但它也不允许任何修改操作,因此它看起来非常合适.