X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;ds=sidebyside;f=0.6.x%2Fjs%2F01_core%2F11_XClass.js;h=e4b556aa53ab1eed7c551f6b0e88eaf7c0dd692f;hb=8e74cf066ea48ec8cf34efb2b5e84725c10c813a;hp=1a5499e02cad620eac0cd0a7be06e61f6348b60f;hpb=50462b7b22a3c42bdbf2fb84d782937f817368f4;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/01_core/11_XClass.js b/0.6.x/js/01_core/11_XClass.js index 1a5499e..e4b556a 100644 --- a/0.6.x/js/01_core/11_XClass.js +++ b/0.6.x/js/01_core/11_XClass.js @@ -5,7 +5,7 @@ var /** * 全てのクラスのスーパークラスのようなもの。(ライブラリ内にカプセル化されているため、ユーザが触ることはありません)
- * X_Class.create() で定義されたクラスのインスタンスが共通で備えるメソッド を確認してください。 + * X.Class.create() で定義されたクラスのインスタンスが共通で備えるメソッド を確認してください。 * @class __ClassBase__ * @private * @abstract @@ -20,11 +20,8 @@ var X_Class_CLASS_LIST = [], X_Class_DEF_LIST = [], - X_Class_PRIVATE_CLASS_LIST = [], - X_Class_PRIVATE_DEF_LIST = [], X_Class_CALLING_SUPER = [], X_Class_CALL_SUPER_STACK = [], - X_Class_killPrivateFlag = false, X_Class_traits = null, X_Class_useObjectCreate = false, // !!Object.create, http://jsperf.com/prototype-vs-object-create-perf X_Class_use_proto_ = !X_UA[ 'OperaMobile' ] && !X_UA[ 'OperaTablet' ] && !!X_emptyFunction.prototype.__proto__, @@ -37,70 +34,50 @@ X_Class_CommonMethods = * 全ての動的メンバを削除して、インスタンスを破棄する。
* インスタンスが X.EventDispatcher とそのサブクラスの場合、次の動作をする。 *
    - *
  1. X.Event.BEFORE_KILL_INSTANCE を発火する。戻り値のビットフラグに X_Callback_PREVENT_DEFAULT が立つ場合、破棄をキャンセルし X.Event.KILL_INSTANCE_CANCELED を発火する。 + *
  2. X.Event.BEFORE_KILL_INSTANCE を発火する。戻り値のビットフラグに X_Callback.PREVENT_DEFAULT が立つ場合、破棄をキャンセルし X.Event.KILL_INSTANCE_CANCELED を発火する。 *
  3. 破棄に進む場合は、X.Event.KILL_INSTANCE を発火する。 *
  4. dispatch 中は、インスタンスの全ての dispatch が終了するまで実際の破棄を待つ。 *
  5. 実際の破棄では、インスタンスのメンバの削除に加えて全てのイベントリスナを解除する。 */ // TODO kill したインスタンスのイベントが残っていないか?これは開発用のみ 'kill' : function(){ - var instance = this, - klass = X_Class_getClass( instance ), - def = X_Class_getClassDef( klass ), - data, p, i; - if( def.isPrivate && !X_Class_killPrivateFlag && ( !this[ '_listeners' ] || !this[ '_listeners' ][ X_Listeners_.KILL_RESERVED ] ) ){ - X.Logger.critical( 'PrivateInstance.kill() work in PrivateUser.kill().' ); - return; - }; - X_Class_killPrivateFlag = false; // instance.kill() 内で PrivateInstance.kill() を防ぐため + var def, listeners, p; + + // TODO kill 中の kill の呼び出しを防ぐ, 破棄済のインスタンスへの kill if( this[ 'instanceOf' ]( X_EventDispatcher ) ){ - if( !def.isPrivate ){ - if( this[ 'dispatch' ]( X_EVENT_BEFORE_KILL_INSTANCE ) & X_Callback_PREVENT_DEFAULT ){ - this[ 'dispatch' ]( X_EVENT_KILL_INSTANCE_CANCELED ); - return; - }; - if( this[ '_listeners' ] && this[ '_listeners' ][ X_Listeners_.DISPATCHING ] ){ - this[ '_listeners' ][ X_Listeners_.KILL_RESERVED ] = true; - return; - }; - } else { - this[ 'dispatch' ]( X_EVENT_BEFORE_KILL_INSTANCE ); + + if( this[ 'dispatch' ]( X_EVENT_BEFORE_KILL_INSTANCE ) & X_Callback_PREVENT_DEFAULT ){ + this[ 'dispatch' ]( X_EVENT_KILL_INSTANCE_CANCELED ); + return; + }; + + listeners = this[ '_listeners' ]; + + if( listeners && listeners[ X_LISTENERS_DISPATCHING ] ){ + listeners[ X_LISTENERS_KILL_RESERVED ] = true; + return; }; // asyncDispatch の削除 for( p in X_EventDispatcher_LAZY_TIMERS ){ if( X_EventDispatcher_LAZY_TIMERS[ p ] === this ){ - delete X_EventDispatcher_LAZY_TIMERS[ p ]; // 削除が先!理由は X.Timer.removeを確認。 - X_Timer_remove( parseFloat( p ) ); + // delete X_EventDispatcher_LAZY_TIMERS[ p ]; コレ不要 + X_Timer_remove( p ); }; }; this[ 'dispatch' ]( X_EVENT_KILL_INSTANCE ); - this[ '_listeners' ] && X_EventDispatcher_unlistenAll( this ); + listeners && X_EventDispatcher_unlistenAll( this ); }; - for( p in instance ){ - if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue; - delete instance[ p ]; - }; + X_Object_clear( this ); + + def = X_Class_getClassDef( this ); + if( def.pool ){ - def.live && def.live.splice( def.live.indexOf( instance ), 1 ); - def.pool[ def.pool.length ] = instance; - }; - if( def.privateClass ){ - i = def.userList.indexOf( instance ); - if( i !== -1 ){ - data = X_Class_getPrivate( instance ); - if( data[ '_listeners' ] && data[ '_listeners' ][ X_Listeners_.DISPATCHING ] && data[ 'instanceOf' ]( X.EventDispatcher ) ){ - data[ '_listeners' ][ X_Listeners_.KILL_RESERVED ] = true; - } else { - X_Class_killPrivateFlag = true; - data[ 'kill' ](); - }; - def.dataList.splice( i, 1 ); - def.userList.splice( i, 1 ); - }; + def.live.splice( def.live.indexOf( this ), 1 ); + def.pool[ def.pool.length ] = this; }; }, @@ -232,9 +209,7 @@ var X_Class = { POOL_OBJECT : 1, ABSTRACT : 2, FINAL : 4, - SUPER_ACCESS : 8, - PRIVATE_DATA : 16, - SINGLETON : 32 + SINGLETON : 8 }; /** @@ -248,7 +223,7 @@ var X_Class = { *
* *
    - *
  1. X_Class.create( opt_settings, opt_name, opt_privateClass, opt_props ) でクラスを登録. + *
  2. X.Class.create( opt_settings, opt_name, opt_props ) でクラスを登録. *
  3. コンストラクタ となるメソッドは、opt_props 内の Constructor : function( arg ){ ... }, に書く. *
  4. 通常通り new で インスタンス生成 *
  5. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される. @@ -257,7 +232,7 @@ var X_Class = { * @namespace X.Class * @alias X.Class */ -X[ 'Class' ] = { +X[ 'Class' ] = /** @lends X.Class */ { /** * 設定なし。 @@ -284,32 +259,14 @@ X[ 'Class' ] = { 'FINAL' : X_Class.FINAL, /** - * 使用を中止。petanR ライブラリ使用プロジェクトから SUPER_ACCESS を消したらここも削除。 - * @const - */ - 'SUPER_ACCESS' : X_Class.SUPER_ACCESS, - - /** - * 内部コード、主に X.UI フレームワークに対して、フレーム外に露出するインスタンスとペアで動作する、シャドウなインスタンスの使用を宣言する。 - * Javascript はインスタンス毎のカプセル化がとてもコスト高。微妙なコスト増で隠蔽されたインスタンスを使う。 - * @const - */ - 'PRIVATE_DATA' : X_Class.PRIVATE_DATA, - - /** * 未実装。でも目印になるので付けておきましょう。 * @const */ 'SINGLETON' : X_Class.SINGLETON, - 'create' : X_Class_create, + 'create' : X_Class_create // TODO collect - - '_newPrivate' : X_Class_newPrivate, - - '_getPrivate' : X_Class_getPrivate - }; @@ -319,23 +276,40 @@ X[ 'Class' ] = { // ------------------------------------------------------------------------- // /** * クラスを定義する。
    - * X_Class.create() によるクラス定義は必ずしもコンストラクタを必要としません。クラス定義時にコンストラクタが未設定の場合、スーパークラスがあればそのコンストラクタを使用します。 - * @alias X_Class.create + * X.Class.create() によるクラス定義は必ずしもコンストラクタ('Constructor')を必要としません。クラス定義時にコンストラクタが未設定の場合、スーパークラスがあればそのコンストラクタを使用します。 + * @alias X.Class.create * @param {string} [displayName] クラスの名前 * @param {number} [classSetting=0] X_Class.POOL_OBJECT | X_Class.FINAL など - * @param {__ClassBase__=} [privateClass] このクラスとペアで動作するシャドウクラス * @param {object} [props={}] このクラスのメンバと関数。コンストラクタは Constructor と書くこと * @return {__ClassBase__} + * @example var myClass = X.Class.create( + * 'myClass', + * X.Class.FINAL, + * { + * name : '', + * Constructor : function( obj ){ + * this.name = obj.name; + * }, + * getName : function(){ + * return this.name; + * }, + * setName : function(v){ + * this.name = v; + * } + * } + * ); */ function X_Class_create( /* displayName, classSetting, privateClass, props */ ){ var args = X_Object_cloneArray( arguments ), displayName = args[ 0 ], classSetting, - opt_pool, opt_abstract, opt_final, opt_private, + opt_pool, opt_abstract, opt_final, privateDef, props, klass, - classDef = {}, hash; + classDef = {}, + cbHash = { proxy : X_Class_actualConstructor, classDef : classDef }; + if( X_Type_isString( displayName ) === true ){ classDef.displayName = displayName; args.shift(); @@ -347,7 +321,6 @@ X[ 'Class' ] = { opt_pool = !!( classSetting & X_Class.POOL_OBJECT ); opt_abstract = !!( classSetting & X_Class.ABSTRACT ); opt_final = !!( classSetting & X_Class.FINAL ); - opt_private = !!( classSetting & X_Class.PRIVATE_DATA ); if( opt_final && opt_abstract ){ X.Logger.critical( 'final & Abstract!' ); return; @@ -357,32 +330,24 @@ X[ 'Class' ] = { classDef.setting = 0; }; - // シャドウクラス - if( X_Class_PRIVATE_CLASS_LIST.indexOf( args[ 0 ] ) !== -1 ){ - privateDef = X_Class_getClassDef( args[ 0 ] ); - if( privateDef.isPrivate !== true ){ - X.Logger.critical( 'PrivateClass not found! please, X_Class.create( X_Class.PRIVATE, {...} ).' ); - return; - } else - if( privateDef.Abstract === true ){ - X.Logger.critical( 'PrivateClass is Abstract!' ); - return; - }; - classDef.privateClass = args.shift(); - }; - // インスタンスのメンバー props = args[ 0 ]; if( !X_Type_isObject( props ) ){ // クラスメンバ用オブジェクトが無しでもクラスは作成可能 props = {}; } else - if( props[ 'Constructor' ] && X_Type_isFunction( props[ 'Constructor' ] ) ){ + if( props[ 'Constructor' ] ){ + //{+dev + if( !X_Type_isFunction( props[ 'Constructor' ] ) ){ + alert( '"Constructor" is not function.' ); + return; + }; + //}+dev classDef.Constructor = props[ 'Constructor' ]; }; - klass = X_Callback_actualClosure( hash = { proxy : X_Class_actualConstructor } ); // TODO hash = classDef - hash.klass = klass; + klass = X_Callback_actualClosure( cbHash ); // TODO callbackHash を class定義の置き場所にしてしまう!なるほど… + cbHash.klass = klass; klass[ 'superClassOf' ] = X_Class_superClassOf; klass[ 'subClassOf' ] = X_Class_subClassOf; @@ -409,25 +374,17 @@ X[ 'Class' ] = { } else if( opt_pool ){ classDef.pool = []; - if( opt_private === false ) classDef.live = []; + classDef.live = []; }; if( opt_final ){ classDef.Final = true; } else { klass[ 'inherits' ] = X_Class_inherits; }; - if( opt_private ){ - if( classDef.privateClass ){ - X.Logger.critical( 'Private Data Class has no PrivateClass!' ); - return; - }; - classDef.isPrivate = true; - X_Class_PRIVATE_CLASS_LIST.push( klass ); - X_Class_PRIVATE_DEF_LIST.push( classDef ); - } else { - X_Class_CLASS_LIST.push( klass ); - X_Class_DEF_LIST.push( classDef ); - }; + + X_Class_CLASS_LIST.push( klass ); + X_Class_DEF_LIST.push( classDef ); + return klass; }; @@ -441,15 +398,7 @@ function X_Class_getClass( instance ){ klass = cList[ --i ]; if( instance.constructor === klass ) return klass; }; - cList = X_Class_PRIVATE_CLASS_LIST; - i = cList.length; - for( ; i; ){ - klass = cList[ --i ]; - if( instance.constructor === klass ) return klass; - }; - if( cList.indexOf( instance ) !== -1 ) return instance; - if( X_Class_CLASS_LIST.indexOf( instance ) !== -1 ) return instance; }; function X_Class_getClassDef( KlassOrInstance ){ @@ -457,43 +406,7 @@ function X_Class_getClassDef( KlassOrInstance ){ if( i === -1 ) i = X_Class_CLASS_LIST.indexOf( X_Class_getClass( KlassOrInstance ) ); if( i !== -1 ) return X_Class_DEF_LIST[ i ]; - i = X_Class_PRIVATE_CLASS_LIST.indexOf( KlassOrInstance ); - if( i === -1 ) i = X_Class_PRIVATE_CLASS_LIST.indexOf( X_Class_getClass( KlassOrInstance ) ); - if( i !== -1 ) return X_Class_PRIVATE_DEF_LIST[ i ]; - if( X_Class_DEF_LIST.indexOf( KlassOrInstance ) !== -1 ) return KlassOrInstance; - if( X_Class_PRIVATE_DEF_LIST.indexOf( KlassOrInstance ) !== -1 ) return KlassOrInstance; -}; - -function X_Class_newPrivate( /* instance, args */ ){ - var args = X_Object_cloneArray( arguments ), - user = args.shift(), - def = X_Class_getClassDef( user ), - privateClass = def.privateClass, - privateDef = X_Class_getClassDef( privateClass ), - i = -1; - if( def.userList ){ - i = def.userList.indexOf( user ); - } else { - def.userList = []; - def.dataList = []; - }; - if( i !== -1 ){ - X.Logger.critical( 'PrivateData already exist!' ); - return; - }; - if( privateDef._tempUser ){ - X.Logger.critical( 'newPrivate を連続呼び出しされたところ破綻' ); - return; - }; - privateDef._tempUser = user; - return X_Class_actualConstructor( privateClass( X_Closure_COMMAND_BACK ), args );// privateClass.__new( args ); -}; - -function X_Class_getPrivate( instance ){ - var def = X_Class_getClassDef( instance ), - i = def.userList.indexOf( instance ); - if( i !== -1 ) return def.dataList[ i ]; }; /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */ @@ -580,16 +493,12 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props // クラス設定がない場合、親からコピーして、Abstract flag は落とす?? classSetting = superDef.setting;// &= ~X_Class.ABSTRACT; }; - if( superDef.isPrivate ) classSetting = classSetting | X_Class.PRIVATE_DATA; params.push( classSetting ); // サブクラスのシャドウ if( args[ 0 ] && X_Class_getClass( args[ 0 ] ) ){ params.push( args.shift() ); - } else - if( superDef.privateClass ){ - params.push( superDef.privateClass ); }; /* props 未定義でも可 */ @@ -622,40 +531,28 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props */ function X_Class_actualConstructor( f, args ){ var klass = f.klass, - def = X_Class_getClassDef( klass ), - dataUser = def._tempUser, - instance, obj, - userDef; + def = f.classDef, + instance, obj; + if( def.Abstract ){ X.Logger.critical( 'AbstractClass!' ); return; }; - if( def.isPrivate && !dataUser ){ - X.Logger.critical( 'use myClass.newPrivate( instance, ...args )!' ); - return; - }; - instance = def.pool && def.pool.length > 0 ? + instance = def.pool && def.pool.length ? def.pool.pop() : X_Class_useObjectCreate ? Object.create( klass.prototype ) : new klass( X_Closure_COMMAND_DROP ); - if( def.isPrivate ){ - userDef = X_Class_getClassDef( dataUser ); - userDef.dataList.push( instance ); - userDef.userList.push( dataUser ); - instance.User = dataUser; - def._tempUser = null; - } else { - def.live && def.live.push( instance ); - }; + def.live && def.live.push( instance ); obj = def.Constructor ? def.Constructor.apply( instance, args ) : def.SuperConstructor && def.SuperConstructor.apply( instance, args ); - if( ( X_Type_isObject( obj ) && obj !== instance ) || X_Type_isFunction( obj ) ){ // Class + + if( obj !== instance && ( X_Type_isObject( obj ) || X_Type_isFunction( obj ) ) ){ // Class instance[ 'kill' ](); return obj; };