Неизменяемые коллекции Actionscript 3

В последнее время я пытаюсь внедрить некоторые чистые методы кодирования в AS3. Одна из них заключалась в том, чтобы не отсылать ссылки на массивы из содержащего объекта. Дело в том, что я контролирую добавление и удаление из одного класса, а все остальные пользователи из массива получают только версию для чтения.

В настоящий момент версия только для чтения представляет собой класс ArrayIterator, который я написал, который реализует типичный интерфейс Iterator (hasNext, getNext). Он также расширяет прокси-сервер, поэтому его можно использовать для каждой петли, как только может быть массив.

Итак, мой вопрос заключается в том, что это не является фундаментальной особенностью многих языков? Возможность передавать ссылки на чтение только видов коллекций?

Также теперь, когда улучшена безопасность типов для коллекций в AS3, в виде класса Vector, когда я обертываю вектор в VectorIterator, я теряю типизацию ради неизменности. Есть ли способ реализовать два желания, неизменность и типизацию в AS3?

Ответ 1

Кажется, что использование шаблона Iterator - лучший способ в настоящее время в AS3 для передачи коллекции вокруг системы, гарантируя, что он не будет изменен.

Используемый мной интерфейс IIterator моделируется на Java Iterator, но я не реализую метод remove(), так как это считается ошибкой дизайна многими в сообществе Java, благодаря чему пользователь может удалить элементы массива. Ниже приведена моя реализация IIterator:

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

Затем это реализуется такими классами, как ArrayIterator, VectorIterator и т.д.

Для удобства я также расширяю Proxy на своих конкретных классах Iterator и поддерживаю for-each петли в AS3, переопределяя методы nextNameIndex() и nextValue(). Это означает, что код, который обычно использует Массивы, не нуждается в изменении при использовании моего 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)
}

Проблема только в том, что пользователю не нужно смотреть на интерфейс IIterator и знать, что они могут использовать цикл for для каждого цикла для итерации по коллекции. Им нужно будет посмотреть на реализацию ArrayIterator, чтобы увидеть это.

Ответ 2

Некоторые утверждают, что тот факт, что вы можете реализовать такие шаблоны, как библиотеки, является аргументом против добавления функций к самому языку (например, разработчики языка С++ обычно говорят об этом).

Ответ 3

У вас есть неизменяемость, которую вы хотите с помощью прокси-объекта или нет? Обратите внимание, что конструктор VectorIterator может иметь обязательный параметр класса. По общему признанию, на данный момент это не дизайнерский подход, но позволяет надеяться, что в будущем все будет улучшаться.

Ответ 4

Я создал небольшую библиотеку неизменяемых классов коллекции для AS3, включая типизированный упорядоченный список, который звучит так, как будто он будет отвечать вашим потребностям. Подробнее см. этот пост в блоге.

Ответ 5

Что-то, что я делаю для достижения этого, состоит в том, чтобы класс, который поддерживает список, возвращает только копию этого списка в getter через slice(). В качестве примера у моего игрового движка есть класс Scene, который поддерживает список всех Beings, которые были добавлены к нему. Затем этот список открывается как копия:

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

(Извините, что возродил старый поток, я наткнулся на это, ища способы реализовать именно то, что отвечает Брайан, и подумал, что я брошу свои 2 цента в этом вопросе).