11

我有一个带有私有字段的类,它是一个可变集合。这个特定实例中的字段是 an ArrayBuffer,尽管我的问题扩展到任何有限的、有序的、随机访问的集合类型。我想公开这个字段而不允许其他人修改它。在Java中,我会添加一个方法,如:

private List<T> theList;

public List<T> getList() {
    return Collections.unmodifiableList(theList);
}

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

在 Scala 中,我希望找到一个合适的特征,其中包含 、 和 (用于按索引检索值)之类的访问iteratorsizeapply但没有修改器。是否存在我还没有找到的这种类型?

4

4 回答 4

9

Scala 集合库是面向不变性的,不变性不仅仅指不允许你修改给定集合的事实,而且保证你的集合永远不会被任何人修改

因此,您不能也不应该从 Scala 中的可变缓冲区中获取像 immutable.Seq 这样的集合作为视图,因为它违反了该保证。

但是你可以很容易地实现不可修改的可变 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
}

用法:

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

编辑 :

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

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

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
}

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

于 2012-11-21T08:33:32.310 回答
2

将您的缓冲区转换为Seq,或作为包的一部分的其他不可修改的集合之一scala.collection

myBuffer.toSeq
于 2012-11-21T06:07:10.623 回答
1

如果你想:

  • 仅使用现有的库函数(不编写自己的包装器)
  • 确保避免复制
  • 确保返回的值不能转换为可修改的东西,那么一种可能性是简单地返回一个迭代器

    def getStuff = array.iterator
    

当然,如果您的规范明确要求您返回 Seq,这不是一个选项,但它

  • for (x <- obj.getStuff)允许调用者使用与 Seq ( )相同的语法对其进行迭代
  • 允许调用者使用obj.getStuff.toSeqor轻松转换为 Seq 或 List obj.getStuff.toList

(请注意,.iterator 的文档没有明确说明返回的对象不能转换为可修改的对象,但 ArrayBuffer.iterator 的当前实现确实给出了不可修改的迭代器。)

于 2016-08-09T09:40:32.000 回答
0

如果myBuffer.toSeq还不够好,您可以编写自己的类来扩展scala.collection.IndexedSeqOptimized将调用委托给基础集合。

于 2012-11-21T08:33:42.153 回答