11

可変コレクションであるプライベートフィールドを持つクラスがあります。この特定のインスタンスのフィールドはですがArrayBuffer、私の質問は、有限の順序付けられたランダムアクセスコレクションタイプにまで及びます。他の人に変更を許可せずに、このフィールドを公開したいと思います。Javaでは、次のようなメソッドを追加します。

private List<T> theList;

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

Javaでは、結果がインターフェイスListを完全に実装していないことを受け入れます。これは、友人がスローするためです。List#addUnsupportedOperationException

iteratorScalaでは、、、、(インデックスで値を取得するための)などのアクセサーを備えた適切な特性を見つけることを期待していますが、ミューテーターはありませsizeん。apply私がまだ見つけていないようなタイプは存在しますか?

4

4 に答える 4

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
}

使用法:

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パッケージの一部である他の変更不可能なコレクションの1つに変換します。

myBuffer.toSeq
于 2012-11-21T06:07:10.623 に答える
1

あなたがしたい場合は:

  • 既存のライブラリ関数のみを使用します(独自のラッパーを作成しないでください)
  • コピーは避けてください
  • 戻り値を変更可能なものにキャストできないことを確認してください。1つの可能性は、単にイテレータを返すことです。

    def getStuff = array.iterator
    

もちろん、仕様でSeqを返す必要がある場合、これはオプションではありませんが、

  • for (x <- obj.getStuff)呼び出し元がSeqの( )と同じ構文を使用して反復できるようにします
  • obj.getStuff.toSeq呼び出し元がまたはを使用して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 に答える