2010年2月19日 星期五

AdvancedObject

已經將這個類別變成一個開源專案,
https://code.google.com/p/actionscript-3-advanced-object/
AdvancedObject
package tw.right929
{
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;
    import flash.utils.getDefinitionByName;
    import flash.utils.getQualifiedClassName;
    
    use namespace flash_proxy
    
    /**
     * 每一個屬性都有bfs_XXX(before set XXX)和afs_XXX(after set XXX)的function,
     * 代表在這個屬性被設定前和設定後,會呼叫的方法,這是可以累加的方法,
     * 比如,若存在bfs_bfs_XXX會在呼叫bfs_XXX之前被呼叫。
     * 
     * 若該屬性是function則還會有bfc_XXX(before call XXX)和afc_XXX(after call XXX)的function,
     * 代表這個方法在被呼叫前和呼叫後,會呼叫的方法,這也是可以累加的方法。
     * 
     * 上述的四個方法,是會混合的,
     * 比如bfc_bfs_XXX這是會在bfs_XXX這個function被呼叫前呼叫的function。
     * 
     * 依然遵守繼承鏈的關係。
     */
    public dynamic class AdvancedObject extends Proxy
    {
        /**
         * 統一改變這個屬於這個類別物件的missFunction
         */
        public static var missFunction:Function    =    function (name:*, rest:Array):* {return undefined};
        /**
         * 統一改變這個屬於這個類別物件的missProperty
         */
        public static var missProperty:Function    =    function (name:*):* {return undefined};
        
        private var _obj:Object            =    new Object();
        private var _properties:Array    =    new Array();
        private var _variables:Array    =    new Array();
        private var _functions:Array    =    new Array();
        private var _needUpdateProperties:Boolean    =    false;
        
        private var _superObj:Object;
        
        private var _missFunction:Function;
        private var _missProperty:Function;
        
        public function AdvancedObject()
        {
            super();
        }
        
        /**
         * 先看自已有沒有這個屬性,若沒有找superObj的,若superObj也沒有,幫自已新增這個屬性。
         */
        override flash_proxy function setProperty(name:*, value:*):void
        {
            if(this[name] == value)
                return;
            
            _needUpdateProperties    =    true;
            
            var old:*    =    this[name];
            
            if(_hasProperty(name))
            {
                _beforeSet(name , value , old);
                _obj[name]    =    value;
                _afterSet(name , value , old);
            }
            else if(_superObj && _superObj.hasOwnProperty(name))
            {
                _beforeSet(name , value , old);
                _superObj[name] = value;
                _afterSet(name , value , old);
            }
            else
            {
                _beforeSet(name , value , old);
                _obj[name]    =    value;
                _afterSet(name , value , old);
            }
        }
        private function _beforeSet(name:* , newValue:* , oldValue:*):void
        {
            if(_hasProperty("bfs_"+name))
            {
                _callProperty("bfs_"+name , [oldValue , newValue]);
            }
        }
        private function _afterSet(name:* , newValue:* , oldValue:*):void
        {
            if(_hasProperty("afs_"+name))
            {
                _callProperty("afs_"+name , [oldValue , newValue]);
            }
        }
        
        /**
         * 這個方法應該要只能刪掉自已的,不能刪掉繼承鏈上的屬性。
         */
        override flash_proxy function deleteProperty(name:*):Boolean
        {
            _needUpdateProperties    =    true;
            return delete _obj[name]; 
        }
        
        /**
         * 先看自已有沒有這個方法,若沒有呼叫superObj的,若superObj也沒有,統一呼叫這個物件的missFunction。
         */
        override flash_proxy function callProperty(name:*, ... rest):*
        {
            return _callProperty(name , rest);
        }
        flash_proxy function _callProperty(name:* , rest:Array):*
        {
            var result:*;
            if(_hasProperty(name))
            {
                _beforeCall(name , rest);
                result    =    _obj[name].apply(this , rest);
                _afterCall(name , rest);
            }
            else if(_superObj && _superObj.hasOwnProperty(name))
            {
                _beforeCall(name , rest);
                if(_superObj is AdvancedObject)
                {
                    result    =    _superObj._callProperty(name , rest);
                }
                else
                {
                    result    =    _superObj[name].apply(this , rest);
                }
                _afterCall(name , rest);
            }
            else
            {
                result    =    missFunction(name , rest);
            }
            return result;
        }
        private function _beforeCall(name:* , parameters:Array):void
        {
            if(_hasProperty("bfc_"+name))
            {
                _callProperty("bfc_"+name , parameters);
            }
        }
        private function _afterCall(name:* , parameters:Array):void
        {
            if(_hasProperty("afc_"+name))
            {
                _callProperty("afc_"+name , parameters);
            }
        }
        
        /**
         * 先看自已有沒有這個屬性,若沒有找superObj的,若superObj也沒有,統一呼叫這個物件的missProperty。
         */
        override flash_proxy function getProperty(name:*):*
        {
            if(_hasProperty(name))
                return _obj[name];
            else if(_superObj && _superObj.hasOwnProperty(name))
                return _superObj[name];
            else
                return missProperty(name);
        }
        
        override flash_proxy function nextName(index:int):String
        {
            updateProperties();
            return _properties[index-1].toString();
        }
        
        override flash_proxy function nextNameIndex(index:int):int
        {
            updateProperties()
            if (index < _properties.length)
                return index + 1;
            else
                return 0;
        }
        
        override flash_proxy function nextValue(index:int):*
        {
            updateProperties();
            return _obj[_properties[index-1]];
        }
        
        override flash_proxy function isAttribute(name:*):Boolean
        {
            return true;
        }
        
        override flash_proxy function getDescendants(name:*):*
        {
            return _obj[name];
        }
        
        /**
         * 尋找是否有這個屬性,包含superObj。
         */
        override flash_proxy function hasProperty(name:*):Boolean
        {
            updateProperties();
            if(_hasProperty(name))
                return true;
            else if(_superObj && _superObj.hasOwnProperty(name))
                return true;
            else
                return false;
        }
        /**
         * 尋找是否有這個屬性,不包含superObj。
         */
        private function _hasProperty(name:*):Boolean
        {
            if(name is QName)
                name    =    name.localName;
            return(name in _obj);
        }
        
        /**
         * 設定父物件。
         */
        public final function set superObj(v:Object):void
        {
            _superObj    =    v;
        }
        public final function get superObj():Object
        {
            return _superObj;
        }
        
        /**
         * 若呼叫了不存在的方法,則會呼叫這個方法,預設值是傳回undefined。
         */
        public final function set missFunction(v:Function):void
        {
            _missFunction    =    v;
        }
        public final function get missFunction():Function
        {
            if(_missFunction)
                return _missFunction;
            return getDefinitionByName(getQualifiedClassName(this))["missFunction"] as Function;
        }
        
        /**
         * 若想取得不存在的屬性,則會呼叫這個方法,預設值是傳回undefined。
         */
        public final function set missProperty(v:Function):void
        {
            _missProperty    =    v;
        }
        public final function get missProperty():Function
        {
            if(_missProperty)
                return _missProperty;
            return getDefinitionByName(getQualifiedClassName(this))["missProperty"] as Function;
        }
        
        
        /**
         * 重整自已的屬性清單。
         */
        private function updateProperties():void
        {
            if(checkNeedUpdate())
            {
                _properties    =    new Array();
                _variables    =    new Array();
                _functions    =    new Array();
                for (var p:String in _obj)
                {
                    _properties.push(p);
                    if(_obj[p] is Function)
                        _functions.push(p);
                    else
                        _variables.push(p);
                }
                _needUpdateProperties    =    false;
            }
        }
        /**
         * 確定自已的屬性是否有變化而需要更新。
         */
        private function checkNeedUpdate():Boolean
        {
            if(_needUpdateProperties)
                return true;
            if(!_superObj)
                return false;
            if(!(_superObj is AdvancedObject))
                return true;
            return false;
        }
    }
}

測試檔
<?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.AdvancedObject;
            
            private function init():void
            {
                var s:Sprite    =    new Sprite();
                trace(s.hasOwnProperty("x"));
                
                var a:AdvancedObject    =    new AdvancedObject();
                a.superObj    =    s;
                a.bfs_x    =    function (oldV:* , newV:*):void
                {
                    trace("bfs_x old="+oldV+"    new="+newV);
                };
                
                a.bfc_bfs_x    =    function (oldV:* , newV:*):void
                {
                    trace("bfc_bfs_x");
                };
                a.afc_bfs_x    =    function (oldV:* , newV:*):void
                {
                    trace("afc_bfs_x");
                };
                
                a._afs_x    =    function (oldV:* , newV:*):void
                {
                    trace("afs_x old="+oldV+"    new="+newV);
                };
                
                a.x    =    10;
                trace(s.x);
                
                var s2:Sprite    =    new Sprite();
                a.bfc_addChild    =    function (child:DisplayObject):void
                {
                    trace("bfc_addChild "+child);
                };
                
                a.bfc_bfc_addChild    =    function (child:DisplayObject):void
                {
                    trace("bfc_bfc_addChild "+child);
                };
                a.afc_bfc_addChild    =    function (child:DisplayObject):void
                {
                    trace("afc_bfc_addChild "+child);
                };
                
                a.afc_addChild    =    function (child:DisplayObject):void
                {
                    trace("afc_addChild "+child);
                }
                a.addChild(s2);
                trace(s.numChildren);
                
                var mc:MovieClip    =    new MovieClip();
                a.superObj    =    mc;
                a.x    =    100;
                trace(mc.x);
                a.addChild(s);
                trace(mc.numChildren);
                a.x    =    100;
                
            }
        ]]>
    </fx:Script>
</s:Application>

輸出結果
bfc_bfs_x
bfs_x old=0 new=10
afc_bfs_x
10
bfc_bfc_addChild [object Sprite]
bfc_addChild [object Sprite]
afc_bfc_addChild [object Sprite]
afc_addChild [object Sprite]
1
bfc_bfs_x
bfs_x old=0 new=100
afc_bfs_x
100
bfc_bfc_addChild [object Sprite]
bfc_addChild [object Sprite]
afc_bfc_addChild [object Sprite]
afc_addChild [object Sprite]
1

目前AdvancedObject已經實現了目標中的Proxy功能。
接下來要做EventListener的部份,
這個部份有比較大的問題,在於沒辦法知道superObj內到底會發出那些Event,
和一個Event會同時觸發多個function。

沒有留言:

張貼留言

追蹤者