2009-03-01 28 views
10

He intentado últimamente implementar algunas prácticas de codificación limpia en AS3. Una de ellas ha sido no dar referencias a matrices de un objeto contenedor. El punto es que controlo la adición y la eliminación de una clase y todos los demás usuarios de la matriz reciben la versión de solo lectura.Colecciones Inmutables Actionscript 3

En el momento en que se leía única versión es una claseArrayIterator escribí, que implementa un típico iterador interfaz (hasNext, getNext). También se extiende Proxy por lo que se puede utilizar en por cada bucles como puede una matriz.

Así que mi pregunta es si esta no es una característica fundamental de muchos idiomas? ¿La capacidad de pasar referencias para leer solo vistas de colecciones?

también ahora que se mejora la seguridad de tipos de colecciones en AS3, en la forma de la clasevectorial, cuando envuelvo un vector en una VectorIterator pierdo escribiendo por el bien de la inmutabilidad. ¿Hay alguna manera de implementar los dos deseos, la inmutabilidad y el tipado en AS3?

Respuesta

4

Parece que usar un patrón Iterator es la mejor manera actual en AS3 para pasar una colección en un sistema, al tiempo que se garantiza que no se modificará.

El IIterator interfaz de uso se basa en el Java Iterator, pero no implementar el remove() método, ya que se considera un error de diseño por muchos en la comunidad de Java, debido a que permite la usuario para eliminar elementos de la matriz. A continuación se muestra mi IIterator IMPLEMENTACIÓN:

public interface IIterator 
{ 
    function get hasNext():Boolean 
    function next():* 
} 

Esto se implementa luego por clases, tales como ArrayIterator, etc. VectorIterator

Para mayor comodidad extiendo también Proxy en mis clases Iterator concretos, y dar apoyo a for-each bucles en AS3 anulando los métodos nextNameIndex() y nextValue(). Esto significa que el código que normalmente usa Arrays no necesita cambiar cuando se usa mi 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) 
} 

El único problema es ... no hay manera para que el usuario mira el interfaz IIterator y saben que pueden utilizar un para cada-bucle para iterar sobre la colección. Tendrían que ver la implementación de ArrayIterator para ver esto.

+0

¿Cuál es la razón de ser del iterador unidireccional? Esto no es una crítica, solo tengo curiosidad. Además, ¿es posible extender esto para proporcionar funcionalidad de tipo de acceso por índice con la sintaxis de paréntesis familiar (myArray [i] = "foo"), sin que el objeto sea dinámico? –

+0

Creo que no leí la documentación del Proxy con la suficiente diligencia la primera vez. La segunda vez parece que esto es exactamente para lo que la clase proxy debe ser utilizada. –

+0

Sí) El Proxy es bastante útil, puedes hacer un clon relativamente completo de la API E4X, pero uno que construye YAML en lugar de XML, ese tipo de cosas, simplemente anula los métodos getProperty & setProperty –

0

Algunos podrían argumentar que el hecho de que pueda implementar tales patrones como bibliotecas es un argumento en contra de agregar características al lenguaje mismo (por ejemplo, los diseñadores de lenguaje C++ suelen decir eso).

+0

Creo que lo que Brian quiso decir es que debería ser parte de la biblioteca central, no del idioma en sí. (AS3 es manejado por ECMA.) – bzlm

+0

En C++, const es parte del lenguaje y se usa con frecuencia para devolver vistas inmutables de variables miembro. Así que esto no es algo que se creía que podría hacerse como una biblioteca. (podría ser implementable ahora, dado que C++ ganó plantillas, pero no en su forma original) –

+1

Sí, me refiero a la biblioteca central, en el caso de AS3. Me pregunto por qué las opiniones inmutables sobre las colecciones no se consideran importantes. Parece una práctica de diseño fundamentalmente buena, poder decir "Te garantizo que esta colección solo se modificará dentro de esta clase". –

0

¿Tiene o no la inmutabilidad que desea a través del objeto proxy? Tenga en cuenta que puede hacer que el constructor VectorIterator tome un parámetro de Clase obligatorio. Es cierto que esto no es amigable con los diseñadores en este momento, pero esperemos que las cosas mejoren en el futuro.

+0

Tengo inmutabilidad ahora a través de la combinación Proxy, Iterator, pero pierdo el tipeo de la clase Vector debido a las funciones sin tipo de objetos Proxy. –

+0

Sí, la adición de un tipo al constructor VectorIterator sería una posible solución para capturar problemas de conversión de tipo de tiempo de ejecución. Mi punto aquí es que me pregunto por qué las colecciones de solo lectura no existen en muchos idiomas/librerías centrales, desde la primera versión. Parecen una buena práctica de diseño. –

+0

No puedo decir por qué no está allí. Pero, si hace que su implementación sea pública y los problemas que tuvo que enfrentar, según la importancia/popularidad, Adobe podría aprovecharla para la próxima versión. AS todavía está en su adolescencia. – dirkgently

0

He creado una pequeña biblioteca de clases de colección inmutables para AS3, incluyendo una lista escrita a máquina ordenado, que suena como que sería satisfacer sus necesidades. Vea this blog post para más detalles.

+0

Gracias David, se ve bien, También he implementado algo bastante similar con el Proxy. Le echaré un vistazo al código, a ver si puedo obtener algunas buenas ideas –

0

Algo que hago para lograr esto es hacer que la clase que mantiene la lista solo devuelva una copia de esa lista en un getter a través del slice(). Como ejemplo, mi motor de juego tiene una clase Scene que mantiene una lista de todos los Beings que se le han agregado. Dicha lista se expone entonces como una copia de este modo:

public function get beings():Vector.<Being> 
{ 
    return _beings.slice(); 
} 

(Lo sentimos revivir un viejo hilo, me encontré con esto mientras busca la manera de poner en práctica exactamente lo que cubre la respuesta de Brian y pensé que iba a tirar mis 2 centavos en sobre el asunto).

Cuestiones relacionadas