OSDN Git Service

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