MyProxy
package tw.right929
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
use namespace flash_proxy
public dynamic class MyProxy extends Proxy
{
private var _obj:Object = new Object();
private var _properties:Array = new Array();
private var _needUpdateProperties:Boolean = false;
public function MyProxy()
{
super();
}
override flash_proxy function callProperty(name:*, ... rest):*
{
trace("callProperty "+name+" "+rest);
return _obj[name].apply(this, rest);
}
override flash_proxy function deleteProperty(name:*):Boolean
{
trace("deleteProperty "+name);
_needUpdateProperties = true;
return delete _obj[name];
}
override flash_proxy function getDescendants(name:*):*
{
trace("getDescendants "+name);
return _obj[name];
}
override flash_proxy function getProperty(name:*):*
{
trace("getProperty "+name)
return _obj[name];
}
override flash_proxy function hasProperty(name:*):Boolean
{
trace("hasProperty "+name);
updateProperties();
return(name in _obj);
}
override flash_proxy function isAttribute(name:*):Boolean
{
trace("isAttribute "+name);
return true;
}
override flash_proxy function nextName(index:int):String
{
trace("nextName "+index);
updateProperties();
return _properties[index-1].toString();
}
override flash_proxy function nextNameIndex(index:int):int
{
trace("nextNameIndex "+index);
updateProperties()
if (index < _properties.length)
return index + 1;
else
return 0;
}
override flash_proxy function nextValue(index:int):*
{
trace("nextValue "+index);
updateProperties();
return _obj[_properties[index-1]];
}
override flash_proxy function setProperty(name:*, value:*):void
{
trace("setProperty "+name+" = "+value);
_needUpdateProperties = true;
_obj[name] = value;
}
private function updateProperties():void
{
if(_needUpdateProperties)
{
_properties = new Array();
for (var p:String in _obj)
_properties.push(p);
_needUpdateProperties = false;
}
}
}
}
nextName ,nextNameIndex ,nextValue
這三個方法的實作要注意,
傳入的index,代表的意思和想像中的不同(請參考下面的執行結果),
index=0 時代表的是一開始,1是代表第一個屬性的index之後依此類推。
TestMyProxy.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application creationComplete="init()" xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768">
<fx:Script>
<![CDATA[
import tw.right929.MyProxy;
private var myP:MyProxy;
private function init():void
{
myP = new MyProxy();
myP["name"] = "one";//setProperty name = one
myP["showName"] = function ():void
{
trace("myName is "+this["name"]);
};//setProperty showName = function Function() {}
trace(myP.name);//getProperty name ; one
trace(myP.showName);//getProperty showName ; function Function() {}
myP.showName();//callProperty showName ; myName is one
delete myP["name"];//deleteProperty name
trace(myP["name"]);//undefined
myP.showName();//callProperty showName ; myName is one
delete myP["showName"];//deleteProperty showName
//myP.showName();//發生錯誤
trace(myP.hasOwnProperty("p1"));//hasProperty p1 ; false
myP["p1"] = "p1";
trace(myP.hasOwnProperty("p1"));//hasProperty p1 ; true
trace("p1" in myP);//hasProperty p1 ; true
myP["p2"] = "p2";
myP["f1"] = function ():void{};
myP["f2"] = function ():void{};
for(var p:* in myP)
{
trace(p);
}
/*
nextNameIndex 0
nextName 1
p2
nextNameIndex 1
nextName 2
f2
nextNameIndex 2
nextName 3
p1
nextNameIndex 3
nextName 4
f1
nextNameIndex 4
*/
myP.p1 = "pp1";
trace(myP.p1);
trace(myP.f1);
}
]]>
</fx:Script>
</s:Application>
可惜,若想使用Proxy的語法糖衣,就失去和Dictionary一樣的key值特性。
上例中,若把myP["p2"]改myP[{}] ,myP["f2"]改myP[{}],
則迴圈中的結果會變成p1 , f1 , [Object object],
這是因為在setProperty時,傳入的name已經被改成QName了,
真是太可惜了。
使用Proxy的特性和prototype的概念,
也許可以做出想要的,非常動態的類別結構。
沒有留言:
張貼留言