[flash] 获取ActionScript 3 Dictionary的大小



Answers

理想情况下,只需在Dictionary中实现一个扩展Proxy类的包装器。 这允许您覆盖和拦截从Dictionary中添加和删除属性,允许新的Dictionary类与原始类完全相同,具有完全相同的语法和能力,并添加一个返回数字的长度函数键。

该实现如下工作。 设置或删除属性时,它会检查属性是否已存在(是否严格等于undefined)并相应地递增或递减内部长度计数器。 此实现还会在其值设置为undefined以保持一致性时自动删除条目。

我为这个问题写了这个字典包装器; 花了大约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接口方法不兼容。

首先, setPropertygetPropertydeleteProperty方法似乎接收无类型name参数,但它们实际上是强类型的QName对象,它们实际上将键限制为String类型名称,就像Object和关联Arrays一样。 Dictionary不受此限制的约束,并允许将对象实例用作唯一键,因此它本质上与Proxy类方法不兼容。 Dictionary类的文档也有一个注释,它明确指出QName对象不能用作键。

同样,Proxy的nextName方法会阻止您出于同样的原因枚举所有Dictionary键,因为它具有强类型返回值String 。 因此,即使setPropertygetProperty实际上接受了名称的无类型键,您仍然无法通过枚举检索它们,因为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;
    }
Question
var d:Dictionary = new Dictionary();
d["a"] = "b";
d["b"] = "z";

如何获取字典的长度/大小(这是2)?




Related