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:
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?
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:
oder Erstellen eines Wrappers, der Seq
erweitert, wenn Sie eine eigene benutzerdefinierte veränderbare Klasse haben.
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.
Wenn Sie möchten:
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
for (x <- obj.getStuff)
) 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.)
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.
Tags und Links scala scala-collections