OSDN Git Service

Version 0.6.131, cleanup X.EventDispatcher.
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 11_XClass.js
index 8a09da7..248b5bd 100644 (file)
@@ -2,7 +2,7 @@
  * Class を定義し システムの管理下に置く.\r
  * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される.\r
  *  1. X.Class.create( opt_settings, opt_name, opt_privateClass, opt_props ) でクラスを登録.\r
- *  2. コンストラクタ となるメソッドは、Constructor : function( arg ){ ... }, に書く.\r
+ *  2. コンストラクタ となるメソッドは、opt_props 内の Constructor : function( arg ){ ... }, に書く.\r
  *  3. 通常通り new で インスタンス生成\r
  *  4. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.\r
  *  5. pool が有効の場合、new で pool されたインスタンスが返される.\r
@@ -22,12 +22,21 @@ var X_Class_CLASS_LIST         = [],
        X_Class_killPrivateFlag    = false,\r
        X_Class_traits             = null,\r
        X_Class_useObjectCreate    = false, // !!Object.create, http://jsperf.com/prototype-vs-object-create-perf\r
-       X_Class_use_proto_         = !!X.emptyFunction.prototype.__proto__;\r
+       X_Class_use_proto_         = !X_UA.OperaMobile && !X_UA.OperaTablet && !!X.emptyFunction.prototype.__proto__,\r
+               // Opera Mobile 12.10 Android11 IS01 でクラスのメンバが欠落する問題に遭遇。__proto__ を使わないと動作,,,\r
 \r
-/* \r
- * X.Class.create で作られたクラスのインスタンスが共通で備えるメソッド \r
- */\r
-var X_Class_CommonProps = {\r
+/** \r
+ * X.Class.create で定義されたクラスのインスタンスが共通で備えるメソッド を格納\r
+ *\r
+ * @class\r
+ */ \r
+X_Class_CommonProps =\r
+\r
+{\r
+       /*\r
+        * インスタンスの破棄。\r
+        * TODO kill したインスタンスのイベントが残っていないか?これは開発用のみ\r
+        */\r
        kill : function(){\r
                var instance = this,\r
                        klass    = X_Class_getClass( instance ),\r
@@ -37,17 +46,18 @@ var X_Class_CommonProps = {
                        X.Logger.critical( 'PrivateInstance.kill() work in PrivateUser.kill().' );\r
                        return;\r
                };\r
-               X_Class_killPrivateFlag = false; // onKill 内で PrivateInstance.kill() を防ぐため\r
-               \r
-               // onKill() === false の場合、kill のキャンセル\r
-               // private      は false での キャンセル は無視される\r
+               X_Class_killPrivateFlag = false; // instance.kill() 内で PrivateInstance.kill() を防ぐため\r
                \r
+               // X.EventDispatcher とそのサブクラスは kill() が呼ばれた通知を発行する。\r
+               // X.Event.BEFORE_KILL_INSTANCE はキャンセル可能(private な class は不可)\r
+               // X.Event.KILL_INSTANCE は、プロパティやイベントリスナの削除直前に発行\r
+               // X.Event.KILL_INSTANCE_CANCELED は kill() がキャンセルされた場合に発行。また dispatchループ中にkill()が呼ばれると一旦キャンセルされ発行。\r
+               //   (flagを立ててdispatchの終わりにkillする)\r
                if( this.instanceOf( X.EventDispatcher ) ){\r
-                       //console.log( 'this.instanceOf( X.EventDispatcher )! ' + this._dispatching );\r
                        if( !def.isPrivate ){\r
-                               if( this._dispatching ){\r
+                               if( this[ '_listeners' ] && this[ '_listeners' ]._dispatching ){\r
                                        this.dispatch( X.Event.BEFORE_KILL_INSTANCE );\r
-                                       this._killReserved = true;\r
+                                       this[ '_listeners' ]._killReserved = true;\r
                                        this.dispatch( X.Event.KILL_INSTANCE_CANCELED );\r
                                        return;\r
                                } else\r
@@ -60,9 +70,6 @@ var X_Class_CommonProps = {
                        };\r
                        this.dispatch( X.Event.KILL_INSTANCE );\r
                        this._listeners && X_EventDispatcher_systemUnlisten( this ); //.unlisten();\r
-               } else\r
-               if( X.Type.isFunction( instance.onKill ) && instance.onKill() === false && !def.isPrivate ){\r
-                       return;\r
                };\r
                \r
                for( p in instance ){\r
@@ -78,8 +85,8 @@ var X_Class_CommonProps = {
                        if( i !== -1 ){\r
                                data = X_Class_getPrivate( instance );\r
                                X_Class_killPrivateFlag = true;\r
-                               if( data._dispatching && data.instanceOf( X.EventDispatcher ) ){\r
-                                       data._killReserved = true;\r
+                               if( data[ '_listeners' ] && data[ '_listeners' ]._dispatching && data.instanceOf( X.EventDispatcher ) ){\r
+                                       data[ '_listeners' ]._killReserved = true;\r
                                } else {\r
                                        data.kill();\r
                                };\r
@@ -89,9 +96,97 @@ var X_Class_CommonProps = {
                };\r
        },\r
        \r
-       // TODO Super\r
-       // superCall\r
+       /*  クラス定義を辿ってスーパークラスのコンストラクタを探す。\r
+        *  呼び出したコンストラクタは配列に控える。\r
+        *  さらに呼ばれた場合、配列を元にさらに奥のコンストラクタを取得\r
+        *  TODO 現在 new しているインスタンスを保持してチェックする\r
+        */\r
+       Super : function(){\r
+               var sClass = this,\r
+                       i      = X_Class_CALLING_SUPER.indexOf( sClass ),\r
+                       n      = -1,\r
+                       l, sList, def, sConst, ret;\r
+       \r
+               if( i === -1 ){\r
+                       X_Class_CALLING_SUPER[ l = X_Class_CALLING_SUPER.length ] = sClass;\r
+                       X_Class_CALL_SUPER_STACK[ l ] = sList = [];\r
+               } else {\r
+                       sList = X_Class_CALL_SUPER_STACK[ i ];\r
+               };\r
+               \r
+               while( sClass ){\r
+                       def    = X_Class_getClassDef( sClass );\r
+                       sClass = def.SuperClass;\r
+                       sConst = def.SuperConstructor;\r
+                       if( sConst && sList[ ++n ] !== sConst ){\r
+                               sList[ n ] = sConst;\r
+                               ret = sConst.apply( this, arguments );\r
+                               --sList.length;\r
+                               if( !sList.length ){\r
+                                       X_Class_CALLING_SUPER.splice( i, 1 );\r
+                                       X_Class_CALL_SUPER_STACK.splice( i, 1 );\r
+                               };\r
+                               return ret;\r
+                       };\r
+               };\r
+               console.log( 'スーパークラスのコンストラクタが見つかりません' );\r
+       },\r
+\r
+       /*\r
+        * func について、親クラスで設定されている同名の関数メンバーを呼び出す\r
+        * 2つ以上の異なる名前で同じ関数がメンバーだった場合、失敗します\r
+        * 例) this.superCall( arguments.callee, param0, param1, ... )\r
+        */\r
+       superCall : function( func /* ...args */ ){\r
+               var sClass = this,\r
+                       args   = arguments,\r
+                       name, p, sFunc, hit = false;\r
+               if( X.Type.isFunction( func ) ){\r
+                       for( p in this ){\r
+                               if( this[ p ] === func ){\r
+                                       name = p;\r
+                                       break;\r
+                               };\r
+                       };\r
+                       if( !name ) return;\r
+               } else {\r
+                       return;\r
+               };\r
+               \r
+               if( X_EMPTY_OBJECT[ name ] ) return;\r
+               \r
+               while( sClass ){\r
+                       def    = X_Class_getClassDef( sClass );\r
+                       sClass = def.SuperClass;\r
+                       sFunc  = sClass.prototype[ name ];\r
+                       if( sFunc === func ){\r
+                               hit = true; // 現在の関数にヒット\r
+                       } else\r
+                       if( hit && X_Object_inObject( name, this ) ){\r
+                               if( X.Type.isFunction( sFunc ) ){\r
+                                       switch( args.length ){\r
+                                               case 1 :\r
+                                                       return sFunc.call( this );\r
+                                               case 2 :\r
+                                                       return sFunc.call( this, args[ 1 ] );\r
+                                               case 3 :\r
+                                                       return sFunc.call( this, args[ 1 ], args[ 2 ] );\r
+                                               case 4 :\r
+                                                       return sFunc.call( this, args[ 1 ], args[ 2 ], args[ 3 ] );\r
+                                               default :\r
+                                                       args = X.Object.cloneArray( args );\r
+                                                       args.shift();\r
+                                                       return sFunc.apply( this, args );\r
+                                       };\r
+                               };\r
+                               break;\r
+                       };\r
+               };\r
+       },\r
        \r
+       /*\r
+        * TODO instanceof に対応したブラウザはそちらを使用\r
+        */\r
        instanceOf : function( klass ){\r
                var Super = this;\r
                if( this.constructor === klass ) return true;\r
@@ -101,17 +196,34 @@ var X_Class_CommonProps = {
                return false;\r
        }\r
 };\r
+\r
 // ------------------------------------------------------------------------- //\r
 // --- interface ----------------------------------------------------------- //\r
 // ------------------------------------------------------------------------- //\r
+\r
+/** @namespace */ \r
 X.Class = {\r
        \r
+       NONE         : 0,\r
+       \r
+    /**\r
+     * インスタンスは破棄時(this.kill())に回収され、次回の new MyClass() 時に再利用されます。\r
+     * @memberof X.Class */\r
        POOL_OBJECT  :  1,\r
+       \r
+       /**\r
+        * 定義するクラスは抽象クラスになります。new AbstractClass() とするとエラーになります。\r
+        * @memberof X.Class */\r
        ABSTRACT     :  2,\r
+       \r
+       \r
+       /** @memberof X.Class */\r
        FINAL        :  4,\r
+       /** @memberof X.Class */\r
        SUPER_ACCESS :  8,\r
+       /** @memberof X.Class */\r
        PRIVATE_DATA : 16,\r
-       \r
+       /** @memberof X.Class */\r
        SINGLETON    : 32, // 未実装\r
        \r
        create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){\r
@@ -173,10 +285,8 @@ X.Class = {
                        classDef.Constructor = props.Constructor;\r
                };\r
 \r
-               // TODO use X.Function\r
-               klass  = X_Closure_actualClosure( hash = { _ : X_Class_actualConstructor } );//new Function( 'var a=arguments,f=a.callee;if(f.__new)return f.__new(a)' );\r
+               klass  = X_Callback_actualClosure( hash = { _ : X_Class_actualConstructor } ); // TODO hash = classDef\r
                hash.c = klass;\r
-               //klass.__new = X_Class_actualConstructor;\r
                klass.superClassOf = X_Class_superClassOf;\r
                klass.subClassOf   = X_Class_subClassOf;\r
                \r
@@ -224,15 +334,9 @@ X.Class = {
                return klass;\r
        },\r
        \r
-       _getClass    : X_Class_getClass,\r
-       \r
-       _getClassDef : X_Class_getClassDef,\r
-       \r
        _newPrivate  : X_Class_newPrivate,\r
        \r
-       _getPrivate  : X_Class_getPrivate,\r
-       \r
-       _override    : X_Class_override\r
+       _getPrivate  : X_Class_getPrivate\r
        \r
 };\r
 \r
@@ -306,8 +410,9 @@ function X_Class_getPrivate( instance ){
 function X_Class_override( target, src, force ){\r
        var p;\r
        for( p in src ){\r
-               if( p === 'Super' || p === 'SuperConstructor' || p === '__proto__' || p === 'prototype' || p === 'constructor' ){\r
-                       X.Logger.critical( 'Super & SuperConstructor is reserved!' );\r
+               if( p === 'Constructor' ) continue;\r
+               if( p === '__proto__' || p === 'prototype' || p === 'constructor' ){\r
+                       X.Logger.critical( p + ' is reserved!' );\r
                        return;\r
                };\r
                if( force || target[ p ] === void 0 ){\r
@@ -346,7 +451,7 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props
                superDef    = X_Class_getClassDef( Super ),\r
                displayName = args[ 0 ],\r
                classSetting,\r
-               opt_super,\r
+               //opt_super,\r
                klass, def;\r
        if( superDef.Final ) X.Logger.critical( 'X.Class inherits, Class is final!' );\r
        \r
@@ -367,7 +472,7 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props
                classSetting = superDef.setting;// &= ~X.Class.ABSTRACT;\r
        };\r
        if( superDef.isPrivate ) classSetting = classSetting | X.Class.PRIVATE_DATA;\r
-       opt_super = !!( classSetting & X.Class.SUPER_ACCESS );\r
+       //opt_super = !!( classSetting & X.Class.SUPER_ACCESS );\r
        params.push( classSetting );\r
 \r
        // サブクラスのシャドウ\r
@@ -377,7 +482,9 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props
        if( superDef.privateClass ){\r
                params.push( superDef.privateClass );\r
        };\r
-       params.push( args[ 0 ] ); /* props サブクラスでは未定義でも可 */\r
+       \r
+       /* props 未定義でも可 */\r
+       params.push( args[ 0 ] );\r
        \r
        // 継承クラスの作成\r
        if( X_Class_useObjectCreate ){\r
@@ -386,23 +493,21 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props
        if( X_Class_use_proto_ ){\r
                X_Class_traits = Super.prototype;\r
        } else {\r
-               //Super.__new = null;\r
                X_Class_traits = new Super( X_Closure_COMMAND_DROP );\r
-               //Super.__new = X_Class_actualConstructor;                      \r
        };\r
        klass  = X.Class.create.apply( X.Class, params );\r
        X_Class_traits = null;\r
        \r
        def    = X_Class_getClassDef( klass );\r
        // 継承用プロパティを控える\r
-       if( opt_super === true ){\r
-               def.superAccess = true;\r
+       //if( opt_super === true ){\r
+               //def.superAccess = true;\r
                def.SuperClass  = Super;\r
                def.SuperProto  = Super.prototype;\r
                def.SuperConstructor = superDef.Constructor || superDef.SuperConstructor;\r
-       } else {\r
-               def.SuperClass = Super; // instanceOf() で親クラスを調べる!\r
-       };\r
+       // else {\r
+       //      def.SuperClass = Super; // instanceOf() で親クラスを調べる!\r
+       //};\r
        \r
        return klass;\r
 };\r
@@ -411,8 +516,8 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props
  * new の実体.コンストラクタの機能は instance.Constructor に書く.\r
  * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる\r
  */\r
-function X_Class_actualConstructor( obj, args ){\r
-       var klass    = obj.c,//this,\r
+function X_Class_actualConstructor( f, args ){\r
+       var klass    = f.c,\r
                def      = X_Class_getClassDef( klass ),\r
                dataUser = def._tempUser,\r
                instance, obj,\r
@@ -425,13 +530,12 @@ function X_Class_actualConstructor( obj, args ){
                X.Logger.critical( 'use myClass.newPrivate( instance, ...args )!' );\r
                return;\r
        };\r
-       //klass.__new = null;\r
+       \r
        instance = def.pool && def.pool.length > 0 ?\r
                                        def.pool.pop() :\r
                                X_Class_useObjectCreate ?\r
                                        Object.create( klass.prototype ) :\r
                                        new klass( X_Closure_COMMAND_DROP );\r
-       //klass.__new = X_Class_actualConstructor;\r
        \r
        if( def.isPrivate ){\r
                userDef = X_Class_getClassDef( dataUser );\r
@@ -442,11 +546,7 @@ function X_Class_actualConstructor( obj, args ){
        } else {\r
                def.live && def.live.push( instance );\r
        };\r
-       if( def.superAccess ){\r
-               // TODO klass.prototype に移動\r
-               instance.Super = def.SuperProto;\r
-               instance.SuperConstructor = X_Class_superConstructor;\r
-       };\r
+\r
        obj = def.Constructor ?\r
                        def.Constructor.apply( instance, args ) :\r
                def.SuperConstructor &&\r
@@ -457,39 +557,5 @@ function X_Class_actualConstructor( obj, args ){
        };\r
        return instance;\r
 };\r
-/*  クラス定義を辿ってスーパークラスのコンストラクタを探す。\r
- *  呼び出したコンストラクタは配列に控える。\r
- *  さらに呼ばれた場合、配列を元にさらに奥のコンストラクタを取得\r
- *  TODO 現在 new しているインスタンスを保持してチェックする\r
- */\r
-function X_Class_superConstructor(){\r
-       var sClass = this,\r
-               i      = X_Class_CALLING_SUPER.indexOf( sClass ),\r
-               n      = -1,\r
-               l, sList, def, sConst, ret;\r
-\r
-       if( i === -1 ){\r
-               X_Class_CALLING_SUPER[ l = X_Class_CALLING_SUPER.length ] = sClass;\r
-               X_Class_CALL_SUPER_STACK[ l ] = sList = [];\r
-       } else {\r
-               sList = X_Class_CALL_SUPER_STACK[ i ];\r
-       };\r
-       \r
-       while( sClass ){\r
-               def    = X_Class_getClassDef( sClass );\r
-               sClass = def.SuperClass;\r
-               sConst = def.SuperConstructor;\r
-               if( sConst && sList[ ++n ] !== sConst ){\r
-                       sList[ n ] = sConst;\r
-                       ret = sConst.apply( this, arguments );\r
-                       --sList.length;\r
-                       if( !sList.length ){\r
-                               X_Class_CALLING_SUPER.splice( i, 1 );\r
-                               X_Class_CALL_SUPER_STACK.splice( i, 1 );\r
-                       };\r
-                       return ret;\r
-               };\r
-       };\r
-};\r
 \r
 console.log( 'X.Core.Class' );\r