Nicht änderbare Ansicht einer veränderbaren Scala-Sammlung

8

Ich habe eine Klasse mit einem privaten Feld, das eine veränderbare Sammlung ist. Das Feld in dieser bestimmten Instanz ist ArrayBuffer , obwohl sich meine Frage auf jeden beliebigen, geordneten, wahlfreien Zugriffssammeltyp erstreckt. Ich möchte dieses Feld offen legen, ohne dass andere es ändern können. In Java würde ich eine Methode wie hinzufügen:

%Vor%

In Java akzeptieren wir nur, dass das Ergebnis ein List ist, das die Schnittstelle List nicht vollständig implementiert, weil #add und Freunde UnsupportedOperationException werfen.

In Scala würde ich erwarten, ein passendes Merkmal mit Accessoren wie iterator , size und apply (zum Abrufen von Werten nach Index) zu finden, aber keine Mutatoren. Gibt es einen solchen Typ, den ich gerade noch nicht gefunden habe?

    
Chris Martin 21.11.2012, 06:00
quelle

4 Antworten

9

Die Scala-Sammlungsbibliothek ist auf Unveränderbarkeit ausgerichtet, und die Unveränderlichkeit bezieht sich nicht nur auf die Tatsache, dass Sie eine bestimmte Sammlung nicht ändern dürfen, sondern auch darauf, dass Sie sicher sind, dass die Sammlung niemals verfügbar sein wird von jemandem geändert .

Sie können also nicht und Sie sollten nicht eine Sammlung wie immutable.Seq als eine Ansicht aus einem veränderlichen Puffer in Scala erhalten, da es diese Garantie bricht.

Aber Sie können das Konzept der nicht änderbaren veränderbaren Seq einfach so implementieren:

%Vor%

Verwendung:

%Vor%

BEARBEITEN:

Eine wahrscheinlich bessere Möglichkeit, eine nicht änderbare Ansicht der Sammlung zu erhalten, besteht darin, zu collection.Seq zu dekrementieren, was keine änderbaren Aktualisierungsoperationen bereitstellt:

%Vor%

oder Erstellen eines Wrappers, der Seq erweitert, wenn Sie eine eigene benutzerdefinierte veränderbare Klasse haben.

%Vor%

Das Merkmal scala.collection.Seq gibt keine Garantien für die Unveränderbarkeit, aber es erlaubt auch keine Modifizierungsoperationen, daher scheint es die perfekte Anpassung zu sein.

    
Marius Danila 21.11.2012, 08:33
quelle
2

Konvertieren Sie Ihren Puffer in eine Seq oder eine der anderen nicht änderbaren Sammlungen, die Teil des Pakets scala.collection sind.

%Vor%     
cheeken 21.11.2012 06:07
quelle
1

Wenn Sie möchten:

  • Verwenden Sie nur vorhandene Bibliotheksfunktionen (schreiben Sie keinen eigenen Wrapper)
  • achte darauf, dass du
  • nicht kopierst
  • stelle sicher, dass der zurückgegebene Wert nicht in etwas veränderbares umgewandelt werden kann dann besteht eine Möglichkeit darin, einfach einen Iterator zurückzugeben

    %Vor%

Dies ist natürlich keine Option, wenn Ihre Spezifikation ausdrücklich verlangt, dass Sie einen Seq zurückgeben, aber es

  • erlaubt dem Aufrufer, mit der gleichen Syntax wie für Seq's ( for (x <- obj.getStuff) )
  • darüber zu iterieren
  • ermöglicht es dem Aufrufer, mithilfe von obj.getStuff.toSeq oder obj.getStuff.toList einfach in eine Seq oder Liste zu konvertieren.

(Beachten Sie, dass die Dokumentation von .iterator nicht explizit besagt, dass das zurückgegebene Objekt nicht in eine änderbare Form umgewandelt werden kann, aber die aktuelle Implementierung von ArrayBuffer.iterator gibt tatsächlich einen nicht änderbaren Iterator.)

    
Dominique Unruh 09.08.2016 09:40
quelle
0

Wenn myBuffer.toSeq nicht gut genug ist, können Sie Ihre eigene Klasse schreiben, die scala.collection.IndexedSeqOptimized erweitert und die Aufrufe an eine zugrunde liegende Sammlung delegiert.

    
Alexey Romanov 21.11.2012 08:33
quelle

Tags und Links