\r
X_Class_CLASS_LIST = [],\r
X_Class_DEF_LIST = [],\r
- X_Class_CALLING_SUPER = [],\r
- X_Class_CALL_SUPER_STACK = [],\r
X_Class_SUPER_CALLER = [],\r
X_Class_SUPER_STACKS = [],\r
X_Class_traits = null,\r
},\r
\r
/**\r
- * 関数は Constructor 内で使用します。クラス定義を辿ってスーパークラスのコンストラクタを探します。<br>\r
+ * 関数は Constructor 内で使用します。クラス定義を辿ってスーパークラスのコンストラクタを呼び出します。<br>\r
* 内部的には、呼び出したコンストラクタは配列に控え(X_Class_CALLING_SUPER)、呼び出したコンストラクタ内でさらに Super が呼ばれた場合、配列を元にさらにスーパーなコンストラクタを辿ります。\r
* @example Constructor : function( arg1, arg2 ){\r
* this.Super( aeg1, arg2 );\r
// TODO 現在 new しているインスタンスを保持してチェックする\r
'Super' : function( var_args ){\r
var me = this,\r
- sClass = me,\r
- i = X_Class_CALLING_SUPER.indexOf( me ),\r
- l, sList, def, sConst, ret;\r
+ sClass = me.constructor,\r
+ i = X_Class_SUPER_CALLER.indexOf( me ),\r
+ stack, t, def, ret;\r
\r
if( i === -1 ){\r
- X_Class_CALLING_SUPER[ l = X_Class_CALLING_SUPER.length ] = me;\r
- X_Class_CALL_SUPER_STACK[ l ] = sList = [];\r
- def = X_Class_getClassDef( me );\r
- if( !def.Constructor ) sClass = def.SuperClass;// 現在のクラスがコンストラクタを持たない場合 SuperConstructor を new で呼んでいるため再び呼ばないようにする\r
+ X_Class_SUPER_CALLER[ i = X_Class_SUPER_CALLER.length ] = me;\r
+ t = stack = X_Class_SUPER_STACKS[ i ] = 0;\r
} else {\r
- sList = X_Class_CALL_SUPER_STACK[ i ];\r
+ t = stack = X_Class_SUPER_STACKS[ i ];\r
+ \r
+ while( t ){\r
+ sClass = X_Class_getClassDef( sClass ).SuperClass;\r
+ --t;\r
+ }; \r
};\r
- \r
+\r
while( sClass ){\r
+ ++t;\r
+ sClass = X_Class_getClassDef( sClass ).SuperClass;\r
+ if( !sClass ) break;\r
def = X_Class_getClassDef( sClass );\r
- sClass = def.SuperClass;\r
- sConst = def.SuperConstructor;\r
- if( !sConst ) break;\r
- if( sList.indexOf( sConst ) === -1 ){\r
- sList[ sList.length ] = sConst;\r
- ret = sConst.apply( me, 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 || me;\r
+ \r
+ if( def.Constructor ){\r
+ X_Class_SUPER_STACKS[ i ] += t;\r
+ ret = def.Constructor.apply( me, arguments );\r
+ break;\r
};\r
};\r
- console.log( 'スーパークラスのコンストラクタが見つかりません' );\r
+ \r
+ if( X_Class_SUPER_STACKS[ i ] === stack ) console.log( 'スーパークラス、またはスーパークラスのコンストラクタは存在しません' );\r
+ \r
+ if( stack === 0 ){\r
+ X_Class_SUPER_CALLER.splice( i, 1 );\r
+ X_Class_SUPER_STACKS.splice( i, 1 );\r
+ } else {\r
+ X_Class_SUPER_STACKS[ i ] = stack;\r
+ };\r
+ return ret || me;\r
},\r
\r
/**\r
- * func について、親クラスで設定されている同名の関数メンバーを呼び出す。<br>\r
- * 第一引数にオーバーライド済の自身の(自身から参照できる)関数を指定します。内部では関数名を調べた上で prototype チェーンをゴリゴリ辿る、特別なことはしていません。\r
- * superCall がネストする場合、arguments.callee でないと正しく現在階層を取得して親関数を知ることができない\r
- * 次の理由によって、関数名で辿ることはやめました\r
+ * myFunc について、スーパークラスで設定されている同名の関数を呼び出す。<br>\r
+ * 低速な関数なので多用されるべきではありません!<br>\r
+ * 第一引数に自身の(自身から参照できる)関数を指定します。内部では関数名を調べた上で prototype チェーンをゴリゴリ辿る、特別なことはしていません。<br>\r
+ * superCall と Super がネストする場合も現在のクラス階層を X_Class_SUPER_CALLER, X_Class_SUPER_STACKS を使って控えているので、意図した親関数が呼ばれます。<br>\r
+ * 次の理由によって、関数名で辿ることは非推奨です。\r
* <ol>\r
* <li>closur compiler でメソッド名が変更される\r
- * <li>superCall 内からさらに superCall が呼ばれた場合に、起点となる関数を特定できない\r
* </ol>\r
- * 次の場合、意図した動作が得られません\r
+ * 次の場合、意図した動作が得られません。\r
* <ol>\r
- * <li>2つ以上の異なる名前で同じ関数がメンバーがいた場合<br>\r
- * <li>または、サブクラスのメンバーにスーパークラスと同じ関数が出現する\r
- * <li>superCall 以外の手段で親関数を呼び、そのなかで superCall を読んだ\r
+ * <li>2つ以上の異なる名前で同じ関数がメンバーがいた場合\r
+ * <li>サブクラスの prototype にスーパークラスと同じ関数をコピーしている\r
+ * <li>非関数でメンバーを上書きしている\r
+ * <li>superCall 以外の手段で親関数を呼び、そのなかで superCall を呼んだ\r
* </ol>\r
- * 通常の X.Class.create の書き方ではこのような状況は起きませんが、js はなんでもできるので\r
- * 参考:<a href="http://qiita.com/no22@github/items/d3bead2acbb7ff1fb86b" target="_blank">ES5なJavascriptでモダンなクラス的継承&スーパー呼び出し </a>\r
+ * 通常の X.Class.create の書き方ではこのような状況は起きませんが、js はなんでもいろいろ出来てしまいますから…<br>\r
+ * 参考:<a href="http://qiita.com/no22@github/items/d3bead2acbb7ff1fb86b" target="_blank">ES5なJavascriptでモダンなクラス的継承&スーパー呼び出し </a><br>\r
+ * original:<a href="http://javascript.crockford.com/inheritance.html" target="_blank">Classical Inheritance in JavaScript</a>\r
* @param myFunc {Function|string} オーバーライド済の自身の(自身から参照できる)関数。\r
* @param var_args {...*} オーバーライド元関数に渡す任意の数の引数\r
- * @example return this.superCall( arguments.callee, param0, param1, ... );\r
+ * @example return this.superCall( this.myFunc, param0, param1, ... );\r
* @return {*} オーバーライド元の関数を呼び出した戻り値。\r
*/\r
'superCall' : function( myFunc, var_args ){\r
sClass = me.constructor,\r
proto = sClass.prototype,\r
i = X_Class_SUPER_CALLER.indexOf( me ),\r
- l, d, ret,\r
args = arguments,\r
- name, p, sFunc, hit;\r
+ p, name, t, sFunc, ret;\r
\r
if( X_Type_isFunction( myFunc ) ){\r
for( p in proto ){\r
};\r
};\r
if( !name ) return;\r
+ } else\r
+ if( X_Type_isString( myFunc ) && X_Type_isFunction( me[ myFunc ] ) ){\r
+ name = myFunc;\r
} else {\r
return;\r
};\r
\r
if( i === -1 ){\r
- X_Class_SUPER_CALLER[ l = X_Class_SUPER_CALLER.length ] = me;\r
- X_Class_SUPER_STACKS[ l ] = d = {};\r
- } else {\r
- d = X_Class_SUPER_STACKS[ i ];\r
- };\r
- \r
- if( stack = d[ name ] ){\r
- myFunc = stack[ stack.length - 1 ];\r
+ X_Class_SUPER_CALLER[ i = X_Class_SUPER_CALLER.length ] = me;\r
+ t = stack = X_Class_SUPER_STACKS[ i ] = 0;\r
} else {\r
- stack = d[ name ] = [];\r
+ t = stack = X_Class_SUPER_STACKS[ i ];\r
+ \r
+ while( t ){\r
+ sClass = X_Class_getClassDef( sClass ).SuperClass;\r
+ --t;\r
+ }; \r
};\r
\r
- /*\r
- while( t ){\r
- sClass = X_Class_getClassDef( sClass ).SuperClass;\r
- --t;\r
- };\r
- mysFunc = sClass.prototype[ name ]; */\r
-\r
+ if( sClass ){\r
+ myFunc = sClass.prototype[ name ];\r
\r
- // TODO \r
- while( sClass ){\r
- sFunc = sClass.prototype[ name ];\r
- \r
- if( !hit && sFunc === myFunc ){\r
- hit = true; // 現在の関数にヒット, さらにスーパークラスを辿って同名のプロパティの関数が現れたらそれが目指すもの\r
- } else\r
- if( hit && sFunc !== myFunc /* X_Object_own( name, sClass.prototype ) */ ){\r
- // this の関数と異なり、値が設定されていたら、今は手を抜いて undef か?見ている、正しくは hasOwnProperty\r
- if( X_Type_isFunction( sFunc ) ){\r
- stack[ stack.length ] = sFunc;\r
- switch( args.length ){\r
- case 0 :\r
- ret = sFunc.call( me );\r
- break;\r
- case 1 :\r
- ret = sFunc.call( me, args[ 0 ] );\r
- break;\r
- case 2 :\r
- ret = sFunc.call( me, args[ 0 ], args[ 1 ] );\r
- break;\r
- case 3 :\r
- ret = sFunc.call( me, args[ 0 ], args[ 1 ], args[ 2 ] );\r
- break;\r
- default :\r
- args = X_Array_copy( args );\r
- args.shift();\r
- ret = sFunc.apply( me, args );\r
- break; \r
+ while( sClass ){\r
+ ++t;\r
+ sClass = X_Class_getClassDef( sClass ).SuperClass; \r
+ sFunc = sClass.prototype[ name ];\r
+ \r
+ if( sFunc !== myFunc /* X_Object_own( name, sClass.prototype ) */ ){\r
+ // this の関数と異なり、値が設定されていたら、今は手を抜いて undef か?見ている、正しくは hasOwnProperty\r
+ if( X_Type_isFunction( sFunc ) ){\r
+ X_Class_SUPER_STACKS[ i ] += t;\r
+ switch( args.length ){\r
+ case 0 :\r
+ ret = sFunc.call( me );\r
+ break;\r
+ case 1 :\r
+ ret = sFunc.call( me, args[ 0 ] );\r
+ break;\r
+ case 2 :\r
+ ret = sFunc.call( me, args[ 0 ], args[ 1 ] );\r
+ break;\r
+ case 3 :\r
+ ret = sFunc.call( me, args[ 0 ], args[ 1 ], args[ 2 ] );\r
+ break;\r
+ default :\r
+ args = X_Array_copy( args );\r
+ args.shift();\r
+ ret = sFunc.apply( me, args );\r
+ break; \r
+ };\r
};\r
- --stack.length;\r
+ break;\r
};\r
- break;\r
};\r
- sClass = X_Class_getClassDef( sClass ).SuperClass; \r
};\r
- \r
- if( !stack.length ) delete d[ name ];\r
- if( X_Object_isEmpty( d ) ){\r
- X_Class_SUPER_CALLER.splice( l, 1 );\r
- X_Class_SUPER_STACKS.splice( l, 1 );\r
+\r
+ if( stack === 0 ){\r
+ X_Class_SUPER_CALLER.splice( i, 1 );\r
+ X_Class_SUPER_STACKS.splice( i, 1 );\r
+ } else {\r
+ X_Class_SUPER_STACKS[ i ] = stack;\r
};\r
return ret;\r
},\r
// --- interface ----------------------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
\r
-/**\r
+/*\r
* @enum {number}\r
* @const\r
*/\r
def = X_Class_getClassDef( klass );\r
// 継承用プロパティを控える\r
def.SuperClass = Super;\r
- def.SuperProto = Super.prototype;\r
- def.SuperConstructor = superDef.Constructor || superDef.SuperConstructor;\r
+ //def.SuperProto = Super.prototype;\r
+ //def.SuperConstructor = superDef.Constructor || superDef.SuperConstructor;\r
\r
return klass;\r
};\r
\r
obj = def.Constructor ?\r
def.Constructor.apply( instance, args ) :\r
- def.SuperConstructor &&\r
- def.SuperConstructor.apply( instance, args );\r
+ instance[ 'Super' ].apply( instance, args );\r
\r
if( obj !== instance && ( X_Type_isObject( obj ) || X_Type_isFunction( obj ) ) ){ // Class\r
instance[ 'kill' ]();\r