I've been trying lately to implement some clean coding practices in AS3. One of these has been to not give away references to Arrays from a containing object. The point being that I control addition and removal from one Class and all other users of the Array receive read only version.
At the moment that read only version is a ArrayIterator class I wrote, which implements a typical Iterator interface (hasNext, getNext). It also extends Proxy so it can be used in for each loops just as a Array can.
So my question is should this not be a fundamental feature of many languages? The ability to pass around references to read only views of collections?
Also now that there is improved type safety for collections in AS3 , in the form of the Vector class, when I wrap a a Vector in a VectorIterator I lose typing for the sake of immutability. Is there a way to implement the two desires, immutability and typing in AS3?
It seems that using an Iterator pattern is the best way currently in AS3 to pass a collection around a system, while guaranteeing that it will not be modified.
The IIterator interface I use is modeled on the Java Iterator, but I do not implement the remove() method, as this is considered a design mistake by many in the Java community, due to it allowing the user to remove array elements. Below is my IIterator implemention:
public interface IIterator
{
function get hasNext():Boolean
function next():*
}
This is then implemented by classes such as ArrayIterator, VectorIterator etc.
For convenience I also extend Proxy on my concrete Iterator classes, and provide support for the for-each loops in AS3 by overriding the nextNameIndex() and nextValue() methods. This means code that typically used Arrays does not need to change when using my IIterator.
var array:Array = ["one", "two", "three"]
for each (var eachNumber:String in array)
{
trace(eachNumber)
}
var iterator:IIterator = new ArrayIterator(array)
for each (var eachNumber:String in iterator)
{
trace(eachNumber)
}
Only problem is... there is no way for the user to look at the IIterator interface and know that they can use a for-each loop to iterate over the collection. They would have to look at the implementation of ArrayIterator to see this.
Some would argue that the fact that you can implement such patterns as libraries is an argument against adding features to the language itself (for example, the C++ language designers typically say that).
Do you have the immutability you want via the proxy object or not? Note, you can have the VectorIterator constructor take a mandatory Class parameter. Admittedly this is not designer friendly at the moment, but lets hope things will improve in the future.
I have created a small library of immutable collection classes for AS3, including a typed ordered list, which sounds like it would meet your needs. See this blog post for details.
Something I do to achieve this is to have the class that maintains the list only return a copy of that list in a getter via slice()
. As an example, my game engine has a class Scene
which maintains a list of all the Beings
that have been added to it. That list is then exposed as a copy like so:
public function get beings():Vector.<Being>
{
return _beings.slice();
}
(Sorry to revive an old thread, I came across this while looking for ways to implement exactly what Brian's answer covers and thought I would throw my 2 cents in on the matter).
来源:https://stackoverflow.com/questions/599825/immutable-collections-actionscript-3