OSDN Git Service

Version 0.6.194, X.UI.Page working.
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 13_XClass.js
1 \r
2 // ------------------------------------------------------------------------- //\r
3 // ------------ local variables -------------------------------------------- //\r
4 // ------------------------------------------------------------------------- //\r
5 var\r
6         /**\r
7          * 全てのクラスのスーパークラスのようなもの。(ライブラリ内にカプセル化されているため、ユーザが触ることはありません)<br>\r
8          * X.Class.create() で定義されたクラスのインスタンスが共通で備えるメソッド を確認してください。\r
9          * @class __ClassBase__\r
10          * @private\r
11          * @abstract\r
12          */\r
13         __ClassBase__ = {\r
14                         /**\r
15                          * クラス名\r
16                          * @type {string}\r
17                          */\r
18                         name         : ''\r
19                 },\r
20 \r
21         X_Class_CLASS_LIST         = [],\r
22         X_Class_DEF_LIST           = [],\r
23         X_Class_SUPER_CALLER       = [],\r
24         X_Class_SUPER_STACKS       = [],\r
25         X_Class_traits             = null,\r
26         X_Class_useObjectCreate    = false, // !!Object.create, http://jsperf.com/prototype-vs-object-create-perf\r
27         // Opera Mobile 12.10 Android11 IS01 でクラスのメンバが欠落する問題に遭遇。__proto__ を辞めると動作,,,\r
28         X_Class_use_proto_         = !X_UA[ 'OperaMobile' ] && !X_UA[ 'OperaTablet' ] && !!X_emptyFunction.prototype.__proto__,\r
29         X_Class_constructorFix     = X_UA[ 'AOSP' ] < 3 || X_UA[ 'iOS' ] < 5,\r
30         X_Class_SEAL_KILLING       = [],\r
31 \r
32 X_Class_CommonMethods =\r
33 /** @lends __ClassBase__.prototype */\r
34 {\r
35         /**\r
36          * 全ての動的メンバを削除して、インスタンスを破棄する。<br>\r
37          * インスタンスが X.EventDispatcher とそのサブクラスの場合、次の動作をする。\r
38          * <ol>\r
39          * <li>X.Event.BEFORE_KILL_INSTANCE を発火する。戻り値のビットフラグに X_Callback.PREVENT_DEFAULT が立つ場合、破棄をキャンセルし X.Event.KILL_INSTANCE_CANCELED を発火する。この間に kill() が呼ばれても無視される。\r
40          * <li>破棄に進む場合は、X.Event.KILL_INSTANCE を発火する。\r
41          * <li>dispatch 中は、インスタンスの全ての dispatch が終了するまで実際の破棄を待つ。\r
42          * <li>実際の破棄では、インスタンスのメンバの削除に加えて全てのイベントリスナを解除する。\r
43          */\r
44         // TODO kill したインスタンスのイベントが残っていないか?これは開発用のみ\r
45         'kill' : function(){\r
46                 var listeners, flag, p, timers, def;\r
47                 \r
48                 // TODO 破棄済のインスタンスへの kill\r
49                 \r
50                 if( this[ 'instanceOf' ]( X_EventDispatcher ) ){\r
51 \r
52                         listeners = this[ '_listeners' ];\r
53 \r
54                         // SEAL のタイミングは、イベント中なので listeners が存在する\r
55                         if( listeners && X_Class_SEAL_KILLING.length && X_Class_SEAL_KILLING.indexOf( this ) !== -1 ) return;\r
56 \r
57                         // listeners がない場合、イベントの登録がないため、BEFORE_KILL_INSTANCE は呼ばれない。\r
58                         // KILL_RESERVED == true の場合、BEFORE_KILL_INSTANCE は呼ばれない。\r
59                         if( listeners && !listeners[ X_LISTENERS_KILL_RESERVED ] && listeners[ X_EVENT_BEFORE_KILL_INSTANCE ] ){\r
60                                 X_Class_SEAL_KILLING[ X_Class_SEAL_KILLING.length ] = this;\r
61                                 \r
62                                 if( this[ 'dispatch' ]( X_EVENT_BEFORE_KILL_INSTANCE ) & X_CALLBACK_PREVENT_DEFAULT ){\r
63                                         this[ 'dispatch' ]( X_EVENT_KILL_INSTANCE_CANCELED );\r
64                                         // BEFORE_KILL_INSTANCE, KILL_INSTANCE_CANCELED 内で kill() しても PREVENT_DEFAULT の場合はこれを無視する。\r
65                                         flag = true;\r
66                                 };\r
67                                 \r
68                                 X_Class_SEAL_KILLING.length === 1 ?\r
69                                         ( X_Class_SEAL_KILLING.length = 0 ) :\r
70                                         X_Class_SEAL_KILLING.splice( X_Class_SEAL_KILLING.indexOf( this ), 1 );\r
71 \r
72                                 if( flag ) return;\r
73                         };\r
74 \r
75                         if( listeners = this[ '_listeners' ] ){// unlisten 等で listeners が破棄されている場合があるので取り直し。\r
76                                 if( listeners[ X_LISTENERS_DISPATCHING ] ){\r
77                                         listeners[ X_LISTENERS_KILL_RESERVED ] = true;\r
78                                         return;\r
79                                 };\r
80                                 \r
81                                 if( listeners[ X_EVENT_KILL_INSTANCE ] ){\r
82                                         X_Class_SEAL_KILLING[ X_Class_SEAL_KILLING.length ] = this;\r
83 \r
84                                         listeners[ X_LISTENERS_KILL_RESERVED ] = false;                                 \r
85                                         this[ 'dispatch' ]( X_EVENT_KILL_INSTANCE );\r
86                                         \r
87                                         X_Class_SEAL_KILLING.length === 1 ?\r
88                                                 ( X_Class_SEAL_KILLING.length = 0 ) :\r
89                                                 X_Class_SEAL_KILLING.splice( X_Class_SEAL_KILLING.indexOf( this ), 1 );\r
90                                 };\r
91                                 \r
92                                 X_EventDispatcher_unlistenAll( this );\r
93                         };\r
94 \r
95                         if( this[ 'instanceOf' ]( Node ) ){\r
96                                 // console.log( 'KILL : ' + this.call( 'outerHTML' ) );\r
97                                 X_Node_onKill( this );\r
98                         };\r
99 \r
100                         timers = X_EventDispatcher_LAZY_TIMERS;\r
101 \r
102                         // asyncDispatch の削除\r
103                         for( p in timers ){\r
104                                 if( timers[ p ] === this ){\r
105                                          // delete X_EventDispatcher_LAZY_TIMERS[ p ]; コレ不要\r
106                                         X_Timer_remove( p );\r
107                                 };\r
108                         };\r
109                 };\r
110                 \r
111                 X_Object_clear( this );\r
112                 \r
113                 def = X_Class_getClassDef( this );\r
114                 \r
115                 if( def.pool ){\r
116                         def.live.splice( def.live.indexOf( this ), 1 );\r
117                         def.pool[ def.pool.length ] = this;\r
118                 };\r
119         },\r
120         \r
121         /**\r
122          * 関数は Constructor 内で使用します。クラス定義を辿ってスーパークラスのコンストラクタを呼び出します。<br>\r
123          * 内部的には、呼び出したコンストラクタは配列に控え(X_Class_CALLING_SUPER)、呼び出したコンストラクタ内でさらに Super が呼ばれた場合、配列を元にさらにスーパーなコンストラクタを辿ります。\r
124          * @example Constructor : function( arg1, arg2 ){\r
125          *      this.Super( aeg1, arg2 );\r
126          * }\r
127          * @param var_args {...?} 親コンストラクタを呼ぶ際に渡す任意の数の引数\r
128          * @return {*}\r
129          */\r
130         // TODO 現在 new しているインスタンスを保持してチェックする\r
131         'Super' : function( var_args ){\r
132                 var me     = this,\r
133                         sClass = me.constructor,\r
134                         i      = X_Class_SUPER_CALLER.indexOf( me ),\r
135                         stack, t, def, ret;\r
136         \r
137                 if( i === -1 ){\r
138                         X_Class_SUPER_CALLER[ i = X_Class_SUPER_CALLER.length ] = me;\r
139                         t = stack = X_Class_SUPER_STACKS[ i ] = 0;\r
140                 } else {\r
141                         t = stack = X_Class_SUPER_STACKS[ i ];\r
142                         \r
143                 while( t ){\r
144                         sClass = X_Class_getClassDef( sClass ).SuperClass;\r
145                     --t;\r
146                 };                      \r
147                 };\r
148 \r
149                 while( sClass ){\r
150                         ++t;\r
151                         sClass = X_Class_getClassDef( sClass ).SuperClass;\r
152                         if( !sClass ) break;\r
153                         def    = X_Class_getClassDef( sClass );\r
154                         \r
155                         if( def.Constructor ){\r
156                                 X_Class_SUPER_STACKS[ i ] += t;\r
157                                 ret = def.Constructor.apply( me, arguments );\r
158                                 break;\r
159                         };\r
160                 };\r
161                 \r
162                 if( X_Class_SUPER_STACKS[ i ] === stack ) console.log( 'スーパークラス、またはスーパークラスのコンストラクタは存在しません' );\r
163                 \r
164                 if( stack === 0 ){\r
165                         X_Class_SUPER_CALLER.splice( i, 1 );\r
166                         X_Class_SUPER_STACKS.splice( i, 1 );\r
167                 } else {\r
168                         X_Class_SUPER_STACKS[ i ] = stack;\r
169                 };\r
170                 return ret || me;\r
171         },\r
172 \r
173         /**\r
174          * myFunc について、スーパークラスで設定されている同名の関数を呼び出す。<br>\r
175          * 低速な関数なので多用されるべきではありません!<br>\r
176          * 第一引数に自身の(自身から参照できる)関数を指定します。内部では関数名を調べた上で prototype チェーンをゴリゴリ辿る、特別なことはしていません。<br>\r
177          * superCall と Super がネストする場合も現在のクラス階層を X_Class_SUPER_CALLER, X_Class_SUPER_STACKS を使って控えているので、意図した親関数が呼ばれます。<br>\r
178          * 次の理由によって、関数名で辿ることは非推奨です。\r
179          * <ol>\r
180          * <li>closur compiler でメソッド名が変更される\r
181          * </ol>\r
182          * 次の場合、意図した動作が得られません。\r
183          * <ol>\r
184          * <li>2つ以上の異なる名前で同じ関数がメンバーがいた場合\r
185          * <li>サブクラスの prototype にスーパークラスと同じ関数をコピーしている\r
186          * <li>非関数でメンバーを上書きしている\r
187          * <li>superCall 以外の手段で親関数を呼び、そのなかで superCall を呼んだ\r
188          * </ol>\r
189          * 通常の X.Class.create の書き方ではこのような状況は起きませんが、js はなんでもいろいろ出来てしまいますから…<br>\r
190          * 参考:<a href="http://qiita.com/no22@github/items/d3bead2acbb7ff1fb86b" target="_blank">ES5なJavascriptでモダンなクラス的継承&スーパー呼び出し </a><br>\r
191          * original:<a href="http://javascript.crockford.com/inheritance.html" target="_blank">Classical Inheritance in JavaScript</a>\r
192          * @param myFunc {Function|string} オーバーライド済の自身の(自身から参照できる)関数。\r
193          * @param var_args {...*} オーバーライド元関数に渡す任意の数の引数\r
194          * @example return this.superCall( this.myFunc, param0, param1, ... );\r
195          * @return {*} オーバーライド元の関数を呼び出した戻り値。\r
196          */\r
197         'superCall' : function( myFunc, var_args ){\r
198                 var me     = this,\r
199                         sClass = me.constructor,\r
200                         proto  = sClass.prototype,\r
201                         i      = X_Class_SUPER_CALLER.indexOf( me ),\r
202                         args   = arguments,\r
203                         p, name, t, sFunc, ret;\r
204 \r
205                 if( X_Type_isFunction( myFunc ) ){\r
206                         for( p in proto ){\r
207                                 if( proto[ p ] === myFunc ){\r
208                                         name = p;\r
209                                         break;\r
210                                 };\r
211                         };\r
212                         if( !name ) return;\r
213                 } else\r
214                 if( X_Type_isString( myFunc ) && X_Type_isFunction( me[ myFunc ] ) ){\r
215                         name = myFunc;\r
216                 } else {\r
217                         return;\r
218                 };\r
219                         \r
220                 if( i === -1 ){\r
221                         X_Class_SUPER_CALLER[ i = X_Class_SUPER_CALLER.length ] = me;\r
222                         t = stack = X_Class_SUPER_STACKS[ i ] = 0;\r
223                 } else {\r
224                         t = stack = X_Class_SUPER_STACKS[ i ];\r
225                         \r
226                 while( t ){\r
227                         sClass = X_Class_getClassDef( sClass ).SuperClass;\r
228                     --t;\r
229                 };                      \r
230                 };\r
231 \r
232         if( sClass ){\r
233                 myFunc = sClass.prototype[ name ];\r
234 \r
235                         while( sClass ){\r
236                                 ++t;\r
237                                 sClass = X_Class_getClassDef( sClass ).SuperClass;      \r
238                                 sFunc  = sClass.prototype[ name ];\r
239                                 \r
240                                 if( sFunc !== myFunc /* X_Object_own( name, sClass.prototype ) */ ){\r
241                                         // this の関数と異なり、値が設定されていたら、今は手を抜いて undef か?見ている、正しくは hasOwnProperty\r
242                                         if( X_Type_isFunction( sFunc ) ){\r
243                                                 X_Class_SUPER_STACKS[ i ] += t;\r
244                                                 switch( args.length ){\r
245                                                         case 0 :\r
246                                                                 ret = sFunc.call( me );\r
247                                                                 break;\r
248                                                         case 1 :\r
249                                                                 ret = sFunc.call( me, args[ 0 ] );\r
250                                                                 break;\r
251                                                         case 2 :\r
252                                                                 ret = sFunc.call( me, args[ 0 ], args[ 1 ] );\r
253                                                                 break;\r
254                                                         case 3 :\r
255                                                                 ret = sFunc.call( me, args[ 0 ], args[ 1 ], args[ 2 ] );\r
256                                                                 break;\r
257                                                         default :\r
258                                                                 args = X_Array_copy( args );\r
259                                                                 args.shift();\r
260                                                                 ret = sFunc.apply( me, args );\r
261                                                                 break;                                                  \r
262                                                 };\r
263                                         };\r
264                                         break;\r
265                                 };\r
266                         };\r
267                 };\r
268 \r
269                 if( stack === 0 ){\r
270                         X_Class_SUPER_CALLER.splice( i, 1 );\r
271                         X_Class_SUPER_STACKS.splice( i, 1 );\r
272                 } else {\r
273                         X_Class_SUPER_STACKS[ i ] = stack;\r
274                 };\r
275                 return ret;\r
276         },\r
277         \r
278         /**\r
279          * インスタンスのクラスか?またはスーパークラスか?調べる。<br>\r
280          * instanceof 構文をサポートしない環境(IE5以下)を想定する場合、必ずこのメソッドを使用すること。<br>\r
281          * クラスのインスタンスか?だけ調べたい場合は this.constructor === klass が高速。\r
282          * @param klass {__ClassBase__} クラス定義\r
283          * @return {boolean}\r
284          */\r
285         // TODO instanceof に対応したブラウザはそちらを使用\r
286         'instanceOf' : function( klass ){\r
287                 var Super = this;\r
288                 if( this.constructor === klass ) return true;\r
289                 while( Super = X_Class_getClassDef( Super ).SuperClass ){\r
290                         if( Super === klass ) return true;\r
291                 };\r
292                 return false;\r
293         }\r
294 };\r
295 \r
296 // ------------------------------------------------------------------------- //\r
297 // --- interface ----------------------------------------------------------- //\r
298 // ------------------------------------------------------------------------- //\r
299 \r
300 /*\r
301  * @enum {number}\r
302  * @const\r
303  */\r
304 var X_Class = {\r
305         NONE         :  0,\r
306         POOL_OBJECT  :  1,\r
307         ABSTRACT     :  2,\r
308         FINAL        :  4,\r
309         SINGLETON    :  8\r
310 };\r
311 \r
312 /**\r
313  * <p>Class を定義し システムの管理下に置く。\r
314  * <p>prototype 継承のブラウザ毎の差異も吸収し、 以下から最適な方法をしてくれる。\r
315  * \r
316  * <ol>\r
317  * <li>Object.create はパフォーマンスが悪そうなので現在は使っていない。\r
318  * <li>SubClass.prototype.__proto__ = SuperClass.prototype;\r
319  * <li>SubClass.prototype = new SuperClass;\r
320  * </ol>\r
321  * \r
322  * <ol>\r
323  * <li>X.Class.create( opt_settings, opt_name, opt_props ) でクラスを登録.\r
324  * <li>コンストラクタ となるメソッドは、opt_props 内の Constructor : function( arg ){ ... }, に書く.\r
325  * <li>通常通り new で インスタンス生成\r
326  * <li>kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.\r
327  * <li>pool が有効の場合、new で pool されたインスタンスが返される.\r
328  * </ol>\r
329  * @namespace X.Class\r
330  * @alias X.Class\r
331  */ \r
332 X[ 'Class' ] = /** @lends X.Class */ {\r
333 \r
334     /**\r
335      * 設定なし。\r
336      * @const\r
337      */ \r
338         'NONE'         : X_Class.NONE,\r
339         \r
340     /**\r
341      * インスタンスは破棄時(this.kill())に回収され、次回の new MyClass() 時に再利用されます。\r
342      * @const\r
343      */\r
344         'POOL_OBJECT'  :  X_Class.POOL_OBJECT,\r
345         \r
346         /**\r
347          * 定義するクラスは抽象クラスになります。new AbstractClass() とするとエラーになります。\r
348          * @const\r
349          */\r
350         'ABSTRACT'     :  X_Class.ABSTRACT,\r
351 \r
352         /**\r
353          * クラスの継承を禁止する。\r
354          * @const\r
355          */\r
356         'FINAL'        :  X_Class.FINAL,\r
357 \r
358         /**\r
359          * 未実装。でも目印になるので付けておきましょう。\r
360          * @const\r
361          */\r
362         'SINGLETON'    : X_Class.SINGLETON,\r
363 \r
364         'create'       : X_Class_create\r
365         \r
366         // TODO collect\r
367 };\r
368 \r
369 \r
370 \r
371 // ------------------------------------------------------------------------- //\r
372 // --- implements ---------------------------------------------------------- //\r
373 // ------------------------------------------------------------------------- //\r
374         /**\r
375          * クラスを定義する。<br>\r
376          * X.Class.create() によるクラス定義は必ずしもコンストラクタ('Constructor')を必要としません。クラス定義時にコンストラクタが未設定の場合、スーパークラスがあればそのコンストラクタを使用します。\r
377          * @alias X.Class.create\r
378          * @param {string} [displayName] クラスの名前\r
379          * @param {number} [classSetting=0] X_Class.POOL_OBJECT | X_Class.FINAL など\r
380          * @param {object} [props={}] このクラスのメンバと関数。コンストラクタは Constructor と書くこと\r
381          * @return {__ClassBase__}\r
382          * @example var myClass = X.Class.create(\r
383          *      'myClass',\r
384          *  X.Class.FINAL,\r
385          *  {\r
386          *       name : '',\r
387          *       Constructor : function( obj ){\r
388          *        this.name = obj.name;\r
389          *       },\r
390          *       getName : function(){\r
391          *        return this.name;\r
392          *       },\r
393          *       setName : function(v){\r
394          *        this.name = v;\r
395          *       }\r
396          *  }\r
397          * );\r
398          */\r
399         function X_Class_create( /* displayName, classSetting, privateClass, props */ ){\r
400                 var args        = X_Array_copy( arguments ),\r
401                         displayName = args[ 0 ],\r
402                         classSetting,\r
403                         opt_pool, opt_abstract, opt_final,\r
404                         privateDef,\r
405                         props,\r
406                         klass,\r
407                         classDef = {},\r
408                         cbHash = { proxy : X_Class_actualConstructor, classDef : classDef };\r
409 \r
410                 if( X_Type_isString( displayName ) === true ){\r
411                         classDef.displayName = displayName;\r
412                         args.shift();\r
413                 };\r
414                 \r
415                 // クラス設定\r
416                 classDef.setting = classSetting = args[ 0 ];\r
417                 if( X_Type_isNumber( classSetting ) ){\r
418                         opt_pool     = !!( classSetting & X_Class.POOL_OBJECT  );\r
419                         opt_abstract = !!( classSetting & X_Class.ABSTRACT     );\r
420                         opt_final    = !!( classSetting & X_Class.FINAL        );\r
421                         if( opt_final && opt_abstract ){\r
422                                 X.Logger.critical( 'final & Abstract!' );\r
423                                 return;\r
424                         };      \r
425                         args.shift();\r
426                 } else {\r
427                         classDef.setting = 0;\r
428                 };\r
429                 \r
430                 // インスタンスのメンバー\r
431                 props = args[ 0 ];\r
432                 if( !X_Type_isObject( props ) ){\r
433                         // クラスメンバ用オブジェクトが無しでもクラスは作成可能\r
434                         props = {};\r
435                 } else\r
436                 if( props[ 'Constructor' ] ){\r
437                         //{+dev\r
438                         if( !X_Type_isFunction( props[ 'Constructor' ] ) ){\r
439                                 alert( '"Constructor" is not function.' );\r
440                                 return;\r
441                         };\r
442                         //}+dev\r
443                         classDef.Constructor = props[ 'Constructor' ];\r
444                 };\r
445 \r
446                 klass  = X_Closure_actualClosure( cbHash ); // TODO callbackHash を class定義の置き場所にしてしまう!なるほど…\r
447                 cbHash.klass = klass;\r
448                 klass[ 'superClassOf' ] = X_Class_superClassOf;\r
449                 klass[ 'subClassOf' ]   = X_Class_subClassOf;\r
450                 \r
451                 if( X_Class_useObjectCreate ){\r
452                         klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonMethods, false );\r
453                         klass.prototype.constructor = klass;\r
454                 } else\r
455                 if( X_Class_use_proto_ ){\r
456                         X_Class_override( klass.prototype, props, true );\r
457                         if( X_Class_traits ){\r
458                                 klass.prototype.__proto__ = X_Class_traits;\r
459                         } else {\r
460                                 X_Class_override( klass.prototype, X_Class_CommonMethods, false );\r
461                         };\r
462                 } else {\r
463                         klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonMethods, false );\r
464                         klass.prototype.constructor = klass;\r
465                 };\r
466                 \r
467                 klass[ 'name' ] = displayName;\r
468                 \r
469                 if( opt_abstract ){\r
470                         classDef.isAbstract = true;\r
471                 } else\r
472                 if( opt_pool ){\r
473                         classDef.pool = [];\r
474                         classDef.live = [];\r
475                 };                      \r
476                 if( opt_final ){\r
477                         classDef.Final = true;\r
478                 } else {\r
479                         klass[ 'inherits' ] = X_Class_inherits;\r
480                 };                      \r
481                 \r
482                 X_Class_CLASS_LIST.push( klass );\r
483                 X_Class_DEF_LIST.push( classDef );                              \r
484 \r
485                 return klass;\r
486         };\r
487 \r
488 \r
489 \r
490 function X_Class_getClass( instance ){\r
491         var cList = X_Class_CLASS_LIST, i;\r
492         \r
493         if( ( i = cList.indexOf( instance.constructor ) ) !== -1 ) return cList[ i ];\r
494         if( cList.indexOf( instance ) !== -1 ) return instance;\r
495 };\r
496 \r
497 // TODO def = klass( X_Closure_COMMAND_BACK )\r
498 function X_Class_getClassDef( KlassOrInstance ){\r
499         var i = X_Class_CLASS_LIST.indexOf( KlassOrInstance );\r
500         if( i === -1 ) i = X_Class_CLASS_LIST.indexOf( X_Class_getClass( KlassOrInstance ) );\r
501         if( i !== -1 ) return X_Class_DEF_LIST[ i ];\r
502         \r
503         if( X_Class_DEF_LIST.indexOf( KlassOrInstance ) !== -1 ) return KlassOrInstance;\r
504 };\r
505 \r
506 /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */\r
507 function X_Class_override( target, src, force ){\r
508         var p;\r
509         for( p in src ){\r
510                 if( p === 'Constructor' ) continue;\r
511                 if( p === '__proto__' || p === 'prototype' || p === 'constructor' ){\r
512                         X.Logger.critical( p + ' is reserved!' );\r
513                         return;\r
514                 };\r
515                 if( force || target[ p ] === undefined ){\r
516                         target[ p ] = src[ p ];\r
517                 };\r
518         };\r
519         return target;\r
520 };\r
521 \r
522 /**\r
523  * スーパークラスか?調べます。\r
524  * @alias __ClassBase__.superClassOf\r
525  * @param klass {__ClassBase__}\r
526  * @return {boolean}\r
527  */\r
528 function X_Class_superClassOf( klass ){\r
529         var myDef      = X_Class_getClassDef( this ),\r
530                 targetDef  = X_Class_getClassDef( klass ),\r
531                 SuperClass = klass;\r
532 \r
533         if( !myDef || !targetDef || this === klass ) return false;\r
534         \r
535         while( SuperClass = X_Class_getClassDef( SuperClass ).SuperClass ){\r
536                 if( SuperClass === this ) return true;\r
537         };\r
538         \r
539         return false;\r
540 };\r
541 \r
542 /**\r
543  * サブクラスか?調べます。\r
544  * @alias __ClassBase__.subClassOf\r
545  * @type {Function}\r
546  * @param klass {__ClassBase__}\r
547  * @return {boolean}\r
548  */\r
549 function X_Class_subClassOf( klass ){\r
550         return klass && X_Class_superClassOf.call( klass, this );\r
551 };\r
552                         \r
553 /**\r
554  * サブクラスを作ります。与える引数は X_Class.create と同じです。http://d.hatena.ne.jp/m-hiyama/20051018/1129605002\r
555  * @alias __ClassBase__.inherits\r
556  * @example var SubClass = SuperClass.inherits( 'Sub', X_Class.FINAL, { ... } );\r
557  * @param {string} [displayName] クラスの名前\r
558  * @param {number} [classSetting=0] X_Class.POOL_OBJECT | X_Class.FINAL など\r
559  * @param {object} [props={}] このクラスのメンバと関数。コンストラクタは Constructor と書くこと\r
560  * @return {__ClassBase__}\r
561  */\r
562 function X_Class_inherits( /* displayName, classSetting, props */ ){\r
563         var args        = X_Array_copy( arguments ),\r
564                 params      = [],\r
565                 Super       = this,\r
566                 superDef    = X_Class_getClassDef( Super ),\r
567                 displayName = args[ 0 ],\r
568                 classSetting,\r
569                 //opt_super,\r
570                 klass, def;\r
571         if( superDef.Final ) X.Logger.critical( 'X.Class inherits, Class is final!' );\r
572         \r
573         // サブクラス名\r
574         if( X_Type_isString( displayName ) ){\r
575                 args.shift();\r
576         } else {\r
577                 displayName = 'SubClass of ' + superDef.displayName;\r
578         };\r
579         params.push( displayName );\r
580         \r
581         // サブクラス設定\r
582         classSetting = args[ 0 ];\r
583         if( X_Type_isNumber( classSetting ) ){\r
584                 args.shift();\r
585         } else {\r
586                 // クラス設定がない場合、親からコピーして、Abstract flag は落とす??\r
587                 classSetting = superDef.setting;// &= ~X_Class.ABSTRACT;\r
588         };\r
589 \r
590         params.push( classSetting );\r
591 \r
592         // サブクラスのシャドウ\r
593         if( args[ 0 ] && X_Class_getClass( args[ 0 ] ) ){\r
594                 params.push( args.shift() );\r
595         };\r
596         \r
597         /* props 未定義でも可 */\r
598         params.push( args[ 0 ] );\r
599         \r
600         // 継承クラスの作成\r
601         if( X_Class_useObjectCreate ){\r
602                 X_Class_traits = Object.create( Super.prototype );\r
603         } else\r
604         if( X_Class_use_proto_ ){\r
605                 X_Class_traits = Super.prototype;\r
606         } else {\r
607                 X_Class_traits = new Super( X_Closure_COMMAND_DROP );\r
608         };\r
609         klass  = X_Class_create.apply( X.Class, params );\r
610         X_Class_traits = null;\r
611         \r
612         def    = X_Class_getClassDef( klass );\r
613         // 継承用プロパティを控える\r
614         def.SuperClass       = Super;\r
615         //def.SuperProto       = Super.prototype;\r
616         //def.SuperConstructor = superDef.Constructor || superDef.SuperConstructor;\r
617         \r
618         return klass;\r
619 };\r
620         \r
621 /*\r
622  * new の実体.コンストラクタの機能は instance.Constructor に書く.\r
623  * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる\r
624  */\r
625 function X_Class_actualConstructor( f, args ){\r
626         var klass    = f.klass,\r
627                 def      = f.classDef,\r
628                 instance, obj;\r
629 \r
630         if( def.isAbstract ){\r
631                 X.Logger.critical( 'AbstractClass!' );\r
632                 return;\r
633         };\r
634         \r
635         instance = def.pool && def.pool.length ?\r
636                                         def.pool.pop() :\r
637                                 X_Class_useObjectCreate ?\r
638                                         Object.create( klass.prototype ) :\r
639                                         new klass( X_Closure_COMMAND_DROP );\r
640 \r
641         def.live && def.live.push( instance );\r
642 \r
643         if( X_Class_constructorFix && instance.constructor !== klass ){\r
644                 console.log( '------- constructor の不一致!' ); // Android2.3.7\r
645                 instance.constructor = klass;\r
646         };\r
647 \r
648         obj = def.Constructor ?\r
649                         def.Constructor.apply( instance, args ) :\r
650                         instance[ 'Super' ].apply( instance, args );\r
651 \r
652         if( obj !== instance && ( X_Type_isObject( obj ) || X_Type_isFunction( obj ) ) ){ // Class\r
653                 instance[ 'kill' ]();\r
654                 return obj;\r
655         };\r
656         \r
657         return instance;\r
658 };\r
659 \r
660 console.log( 'X.Core.Class' );\r