OSDN Git Service

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