Помимо создания динамических свойств и методов в Proxy (
flash.utils.Proxy) есть возможность управлять порядком перечисления свойств в циклах for..in и for each..in. Для этого используются методы класса:
- nextName(index:int):String
- nextValue(index:int):*
- nextNameIndex(index:int):int
Метод nextName возвращает название свойства по порядковому номеру для цикла for..in (аналогично nextValue для цикла for each..in). nextNameIndex вызывается перед началом каждой итерации в цикле и отвечает за две вещи:
1) предоставляет порядковый номер для nextName и nextValue (если возвращаемое значение >0), или
2) прерывает цикл (если возвращаемое значение равно нулю).
При начале цикла nextNameIndex получает порядковый номер равный нулю. Каждое последующее значение возвращаемое nextNameIndex отлично от нуля и передается методам nextName и nextValue. Если nextNameIndex возвращает ноль, то цикл заканчивается.
К примеру, proxy имеет 3 свойства (x,y,visible), попробуем их перечислить в цикле for..in
Код:
for (var prop:String in proxy) {
trace(prop);
}
Здесь будут вызываться методы nextNameIndex и nextName:
Код:
for (var prop:String in proxy) {
[ proxy.nextNameIndex(0) -> return 1 ]
[ proxy.nextName(1) -> return "x" ]
[ prop = "x" ]
trace(prop); // x
(end for block, repeat)
[ proxy.nextNameIndex(1) -> return 2 ]
[ proxy.nextName(2) -> return "y" ]
[ prop = "y" ]
trace(prop); // y
(end for block, repeat)
[ proxy.nextNameIndex(2) -> return 3 ]
[ proxy.nextName(3) -> return "visible" ]
[ prop = "visible" ]
trace(prop); // visible
[ proxy.nextNameIndex(3) -> return 0 ]
(0 index, break from for block)
}
Если использовать цикл for each..in, то nextValue будет вызываться вместо nextName.
Поскольку в циклах используется порядковый номер, то удобно хранить динамические свойства в массиве и в методах nextName или nextValue просто вернуть элемент массива index-1 (поскольку nextName и nextValue никогда не получают порядкового номера 0).
Создадим прокси-класс, который реализует пример выше. Помните, что методы proxy определены в пространстве имен flash_proxy.
Код:
package {
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class ProxyEnum extends Proxy {
private var props:Array = ["x", "y", "visible"]; // массив свойств
// nextNameIndex вызывается при начале итерации в цикле
override flash_proxy function nextNameIndex (index:int):int {
if (index < props.length) {
// первый вызов 0, возвращаем 1 + index
// т.е. порядковый номер будет 1, затем 2, 3
return index + 1;
} else {
// все свойства перечислены для прерывания цикла
// возвращаем 0
return 0;
}
}
// nextName вызывается после nextNameIndex и порядковый номер начинается с 1
override flash_proxy function nextName(index:int):String {
// возвращаем элемент массива index – 1
return props[index - 1];
}
}
}
Пример использования:
Код:
var proxy:ProxyEnum = new ProxyEnum();
for (var prop in proxy) {
trace(prop);
}
/* output:
x
y
visible
*/
Для полной картины необходимо еще переопределить методы nextValue и getProperty. Но для них нужны возвращаемые значения, пусть класс принимает в конструкторе ссылку на какой-то отображаемый объект, его свойства и будем возвращать.
Код:
package {
import flash.display.DisplayObject;
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class ProxyEnum extends Proxy {
private var props:Array = ["x", "y", "visible"]; // массив свойств
private var _target:DisplayObject;
function ProxyEnum(target:DisplayObject) {
_target = target;
}
// nextNameIndex вызывается при начале итерации в цикле
override flash_proxy function nextNameIndex (index:int):int {
if (index < props.length) {
// первый вызов 0, возвращаем 1 + index
// т.е. порядковый номер будет 1, затем 2, 3
return index + 1;
} else {
// все свойства перечислены для прерывания цикла
// возвращаем 0
return 0;
}
}
// nextName вызывается после nextNameIndex и порядковый номер начинается с 1
override flash_proxy function nextName(index:int):String {
// возвращаем элемент массива index – 1
return props[index - 1];
}
// nextValue вызывается после nextNameIndex в циклах for each..in
override flash_proxy function nextValue(index:int):* {
// получаем название свойства из массива
var prop:String = props[index - 1];
// и возвращаем его значение
return _target[prop];
}
// возвращает значение свойства по его имени
override flash_proxy function getProperty(name:*):* {
return _target[name];
}
}
}
Пример использования:
Код:
var proxy:ProxyEnum = new ProxyEnum(my_mc);
for (var prop:String in proxy) { // nextName/nextNameIndex
trace(prop);
trace(proxy[prop]); // getProperty
}
/* output:
x
34
y
76
visible
true
*/
for each(var value:* in proxy) { // nextValue/nextNameIndex
trace(value);
}
/* output:
34
76
true
*/