* 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
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
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
};\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
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
};\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
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
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
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
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
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
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
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
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
* 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
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
} 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
};\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