2010年2月12日 星期五

ActionScript 3.0 Function Class 相關測試



TestClass的程式碼






package tw.right929
{
    public class TestClass
    {
        private var _name:String;
       
        private var _showNameF:Function;
       
        public function TestClass(name:String)
        {
            _name    =    name;
        }
       
        public function showName():void
        {
            _showNameF(this);
        }
       
        public function set showNameF(v:Function):void
        {
            _showNameF    =    v;
        }
       
        public function get showNameF():Function
        {
            return _showNameF;
        }
    }
}

測試TestFunction傳入Function後,呼叫Function的This會是那個物件?





<?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.TestClass;
           
            private var tc1:TestClass    =    new TestClass("one");
            private var tc2:TestClass    =    new TestClass("two");
           
            private function init():void
            {
                trace("主執行檔是"+this.toString());
//主執行檔是TestFunction
               
                tc1.showNameF    =    showName1;
                tc2.showNameF    =    showName2;
                tc1.showName();
                tc2.showName();
            }
           
            private function showName1(self:*):void
            {
                trace("showName1 的this是"+this.toString());
//showName1 的this是TestFunction
            }
            private function showName2(self:*):void
            {
                trace("showName2 的this是"+this.toString());
//showName2 的this是TestFunction
            }
        ]]>
    </fx:Script>
</s:Application>
由上面的結果,可以知道,傳入的Function的this會是建立這個Function的物件。
這裡還可以注意到showName1和showName2是private的,
但若是自已把參照傳出去的話,則其他的類別是可以呼叫的。

修改TestClass.showName()





        public function showName():void
        {
            //_showNameF(this);
            _showNameF.call(this , this);
        }
執行後結果同上。
使用Function.apply結果亦同。

接下來修改TestFunction





            //*
            private var showName1:Function    =   
                function (self:*):void
                {
                    trace("showName1 的this是"+this.toString());
                    trace("showName1 的self是"+self);
                };
            private var showName2:Function    =   
                function (self:*):void
                {
                    trace("showName1 的this是"+this.toString());
                    trace("showName1 的self是"+self);
                };
           
            /*/
            private function showName1(self:*):void
            {
                trace("showName1 的this是"+this.toString());
//showName1 的this是[object TestClass]
                trace("showName1 的self是"+self);
//showName1 的self是[object TestClass]
               
            }
            private function showName2(self:*):void
            {
                trace("showName2 的this是"+this.toString());
                trace("showName1 的self是"+self);
                trace(toString());
            }
            //*/
執行後,結果有了變化,this變成[object TestClass],
也就是叫呼這個Function的物件實體。
由這個結果可知,若是直接在Class中定義function,
則這個Function會和Class產生很強的關聯,
使用Function.call時,this不會被傳入的參數所影響。
但若是用var的方式產生Function,
則這個Function就不會和特定的Class產生關聯,
全視呼叫時傳入的參數而定。



再來試試存取private的變數。
修改TestFunction





private var showName1:Function    =   
                function (self:*):void
                {
                    trace("showName1 的this是"+this.toString());
                    trace("showName1 的_name是"+this._name);
                };

執行…噹噹…發生錯誤,找不到private的變數。
把_name改成public後,就可以正常執行。
這是因為Function是個Object的關係。

TestClass可以進一步簡化成





package tw.right929
{
    public class TestClass
    {
        public var _name:String;
       
        private var _showName:Function;
       
        public function TestClass(name:String)
        {
            _name    =    name;
        }
       
        public function set showName(v:Function):void
        {
            _showName    =    v;
        }
       
        public function get showName():Function
        {
            return _showName;
        }
    }
}

因為Function.call(this),等價於Function()


故若想於執行期動態的改變Class的方法,
可使用var的方法宣告、傳入,但存取private變數時要注意一下。





測試動態產生的function
修改TestFunction


            private function init():void
            {
                trace("主執行檔是"+this.toString());
               
                //tc1.showName    =    showName1;
                //tc2.showName    =    showName2;
                tc1.showName    =    getF("i am one");
                tc2.showName    =    getF("i am two");
                tc1.showName();//i am one
                tc2.showName();//i am two
            }
           
            private function getF(v:String):Function
            {
                return function ():void
                {
                    trace(v);
                };
            }

從輸出結果可知,每一個function宣告所產生出來的Function都是獨立的個體。

沒有留言:

張貼留言

追蹤者