В идеале можно просто реализовать обертку вокруг Dictionary, которая расширяет класс Proxy.Это позволяет вам переопределять и перехватывать добавление и удаление свойств из словаря, позволяя использовать новый класс Dictionary точно так же, как и оригинал, с точно таким же синтаксисом и возможностями, с добавлением функции длины, которая возвращает числоkeys.
Эта реализация работает следующим образом.Когда свойство установлено или удалено, оно проверяет, существует ли свойство уже (равно ли оно строго неопределено), и соответственно увеличивает или уменьшает внутренний счетчик длины.Эта реализация также автоматически удаляет запись, когда ее значение установлено как неопределенное для согласованности.
Я написал эту словарь-обертку только для этого вопроса;это заняло около 5 минут, и оно предоставляет функцию длины, которая возвращает длину.Я решил сделать его функцией, а не свойством, чтобы оно не мешало именам свойств или перечислению свойств словаря.
НЕ ИСПОЛЬЗУЙТЕ ЭТО ОСУЩЕСТВЛЕНИЕ;ИСПОЛЬЗУЙТЕ ТО, ЧТО В СЛЕДУЮЩЕМ.Я объясню, почему ниже.
package flos.utils
{
import flash.utils.flash_proxy;
import flash.utils.Proxy;
public class Dictionary extends Proxy
{
private var d:flash.utils.Dictionary;
private var _length:int = 0;
public function Dictionary( weakKeys:Boolean = false )
{
d = new flash.utils.Dictionary( weakKeys );
}
public function length():int
{
return _length;
}
override flash_proxy function getProperty(name:*):*
{
return d[name];
}
override flash_proxy function setProperty(name:*, value:*):void
{
if (value === undefined) //delete property when explicitly set to undefined, to enforce rule that an undefined property does not exist and is not counted
{
delete this[name];
return;
}
if (d[name] === undefined)
_length++;
d[name] = value;
}
override flash_proxy function deleteProperty(name:*):Boolean
{
if (d[name] !== undefined)
{
delete d[name];
_length--;
return true;
}
return false;
}
}
}
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Реализация выше, хотя наиболее многообещающий подход, который мог бы работать в теории, в конечном итоге является тупиком, поскольку Dictionary по своей сути несовместим с методами интерфейса Proxy.
Во-первых, методы setProperty
, getProperty
и deleteProperty
, кажется, получают нетипизированные name
параметры, но на самом деле они являются строго типизированными QName
объектами, которые по существу ограничивают ваши ключи String
.введите имена, как Object
и связанные массивы.Dictionary
не ограничен этим ограничением и позволяет использовать экземпляры объекта в качестве уникальных ключей, поэтому он по своей сути несовместим с методами класса Proxy.Документация класса Dictionary также содержит одну заметку, в которой прямо указано, что объекты QName нельзя использовать в качестве ключей.
Аналогично, метод nextName
Proxy не позволяет перечислять все ключи Dictionary
дляПо той же причине, поскольку оно имеет возвращаемое значение строго типа String
.Таким образом, даже если setProperty
, getProperty
фактически принимают нетипизированные ключи для имен, вы все равно не сможете получить их с помощью перечисления, потому что метод nextName
возвращает только строку типа.Dictionary
просто находится в своем собственном классе.
Лучшее, что вы можете сделать, - это реализовать обертку, подобную той, что описана выше, которая предоставляет базовый словарь для перечисления, но другие требуют вызова явных методов addKey / removeKey снетипизированные имена и значения вместо использования поведения Proxy.
Учитывая все вышеперечисленное, лучшая реализация будет выглядеть следующим образом, где вы будете манипулировать словарем, вызывая такие методы, как getValue / setValue / removeValue идоступ к перечислению ключей, а также к свойству length:
public class Dictionary
{
private var d:flash.utils.Dictionary;
private var _keys:Array;
public function Dictionary( weakKeys:Boolean = false )
{
d = new flash.utils.Dictionary( weakKeys );
_keys = new Array();
}
public function get keys():Array
{
return _keys.concat(); //return copy of keys array
}
public function get length():int
{
return _keys.length;
}
public function containsKey( key:* ):Boolean
{
return d[key] !== undefined;
}
public function setValue( key:*, value:* ):void
{
if (value === undefined) //delete property when explicitly set to undefined, to enforce rule that an undefined property does not exist and is not counted
{
removeValue( key );
return;
}
if (d[key] === undefined)
{
_keys.push( key );
}
d[key] = value;
}
public function getValue( key:* ):*
{
return d[key];
}
public function removeValue( key:* ):Boolean
{
if (d[key] !== undefined)
{
delete d[key];
var i:int = _keys.indexOf( key );
if (i > -1)
_keys.splice( i, 1 );
return true;
}
return false;
}