OSDN Git Service

286847872a5b75ec02d7e944b560b210b8b4e19e
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 11_XClass.js
1 /**\r
2  * Class を定義し システムの管理下に置く.\r
3  * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される.\r
4  *  1. X.Class.create( opt_settings, opt_name, opt_privateClass, opt_props ) でクラスを登録.\r
5  *  2. コンストラクタ となるメソッドは、opt_props 内の Constructor : function( arg ){ ... }, に書く.\r
6  *  3. 通常通り new で インスタンス生成\r
7  *  4. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.\r
8  *  5. pool が有効の場合、new で pool されたインスタンスが返される.\r
9  *  6. \r
10  * \r
11  */\r
12 \r
13 // ------------------------------------------------------------------------- //\r
14 // ------------ local variables -------------------------------------------- //\r
15 // ------------------------------------------------------------------------- //\r
16 var X_Class_CLASS_LIST         = [],\r
17         X_Class_DEF_LIST           = [],\r
18         X_Class_PRIVATE_CLASS_LIST = [],\r
19         X_Class_PRIVATE_DEF_LIST   = [],\r
20         X_Class_CALLING_SUPER      = [],\r
21         X_Class_CALL_SUPER_STACK   = [],\r
22         X_Class_killPrivateFlag    = false,\r
23         X_Class_traits             = null,\r
24         X_Class_useObjectCreate    = false, // !!Object.create, http://jsperf.com/prototype-vs-object-create-perf\r
25         X_Class_use_proto_         = !!X.emptyFunction.prototype.__proto__,\r
26 \r
27 /** \r
28  * X.Class.create で定義されたクラスのインスタンスが共通で備えるメソッド を格納\r
29  *\r
30  * @class\r
31  */ \r
32 X_Class_CommonProps =\r
33 \r
34 {\r
35         /*\r
36          * インスタンスの破棄。\r
37          * TODO kill したインスタンスのイベントが残っていないか?これは開発用のみ\r
38          */\r
39         kill : function(){\r
40                 var instance = this,\r
41                         klass    = X_Class_getClass( instance ),\r
42                         def      = X_Class_getClassDef( klass ),\r
43                         data, p, i;\r
44                 if( def.isPrivate && !X_Class_killPrivateFlag ){\r
45                         X.Logger.critical( 'PrivateInstance.kill() work in PrivateUser.kill().' );\r
46                         return;\r
47                 };\r
48                 X_Class_killPrivateFlag = false; // onKill 内で PrivateInstance.kill() を防ぐため\r
49                 \r
50                 // onKill() === false の場合、kill のキャンセル\r
51                 // private      は false での キャンセル は無視される\r
52                 \r
53                 if( this.instanceOf( X.EventDispatcher ) ){\r
54                         //console.log( 'this.instanceOf( X.EventDispatcher )! ' + this._dispatching );\r
55                         if( !def.isPrivate ){\r
56                                 if( this._dispatching ){\r
57                                         this.dispatch( X.Event.BEFORE_KILL_INSTANCE );\r
58                                         this._killReserved = true;\r
59                                         this.dispatch( X.Event.KILL_INSTANCE_CANCELED );\r
60                                         return;\r
61                                 } else\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                                         return;\r
65                                 };\r
66                         } else {\r
67                                 this.dispatch( X.Event.BEFORE_KILL_INSTANCE );  \r
68                         };\r
69                         this.dispatch( X.Event.KILL_INSTANCE );\r
70                         this._listeners && X_EventDispatcher_systemUnlisten( this ); //.unlisten();\r
71                 } else\r
72                 if( X.Type.isFunction( instance.onKill ) && instance.onKill() === false && !def.isPrivate ){\r
73                         return;\r
74                 };\r
75                 \r
76                 for( p in instance ){\r
77                         if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue;\r
78                         delete instance[ p ];\r
79                 };\r
80                 if( def.pool ){\r
81                         def.live && def.live.splice( def.live.indexOf( instance ), 1 );\r
82                         def.pool[ def.pool.length ] = instance;\r
83                 };\r
84                 if( def.privateClass ){\r
85                         i = def.userList.indexOf( instance );\r
86                         if( i !== -1 ){\r
87                                 data = X_Class_getPrivate( instance );\r
88                                 X_Class_killPrivateFlag = true;\r
89                                 if( data._dispatching && data.instanceOf( X.EventDispatcher ) ){\r
90                                         data._killReserved = true;\r
91                                 } else {\r
92                                         data.kill();\r
93                                 };\r
94                                 def.dataList.splice( i, 1 );\r
95                                 def.userList.splice( i, 1 );\r
96                         };\r
97                 };\r
98         },\r
99         \r
100         /*  クラス定義を辿ってスーパークラスのコンストラクタを探す。\r
101          *  呼び出したコンストラクタは配列に控える。\r
102          *  さらに呼ばれた場合、配列を元にさらに奥のコンストラクタを取得\r
103          *  TODO 現在 new しているインスタンスを保持してチェックする\r
104          */\r
105         Super : function(){\r
106                 var sClass = this,\r
107                         i      = X_Class_CALLING_SUPER.indexOf( sClass ),\r
108                         n      = -1,\r
109                         l, sList, def, sConst, ret;\r
110         \r
111                 if( i === -1 ){\r
112                         X_Class_CALLING_SUPER[ l = X_Class_CALLING_SUPER.length ] = sClass;\r
113                         X_Class_CALL_SUPER_STACK[ l ] = sList = [];\r
114                 } else {\r
115                         sList = X_Class_CALL_SUPER_STACK[ i ];\r
116                 };\r
117                 \r
118                 while( sClass ){\r
119                         def    = X_Class_getClassDef( sClass );\r
120                         sClass = def.SuperClass;\r
121                         sConst = def.SuperConstructor;\r
122                         if( sConst && sList[ ++n ] !== sConst ){\r
123                                 sList[ n ] = sConst;\r
124                                 ret = sConst.apply( this, arguments );\r
125                                 --sList.length;\r
126                                 if( !sList.length ){\r
127                                         X_Class_CALLING_SUPER.splice( i, 1 );\r
128                                         X_Class_CALL_SUPER_STACK.splice( i, 1 );\r
129                                 };\r
130                                 return ret;\r
131                         };\r
132                 };\r
133                 console.log( 'スーパークラスのコンストラクタが見つかりません' );\r
134         },\r
135 \r
136         /*\r
137          * func について、親クラスで設定されている同名の関数メンバーを呼び出す\r
138          * 2つ以上の異なる名前で同じ関数がメンバーだった場合、失敗します\r
139          * 例) this.superCall( arguments.callee, param0, param1, ... )\r
140          */\r
141         superCall : function( func /* ...args */ ){\r
142                 var sClass = this,\r
143                         args   = arguments,\r
144                         name, p, sFunc, hit = false;\r
145                 if( X.Type.isFunction( func ) ){\r
146                         for( p in this ){\r
147                                 if( this[ p ] === func ){\r
148                                         name = p;\r
149                                         break;\r
150                                 };\r
151                         };\r
152                         if( !name ) return;\r
153                 } else {\r
154                         return;\r
155                 };\r
156                 \r
157                 if( X_EMPTY_OBJECT[ name ] ) return;\r
158                 \r
159                 while( sClass ){\r
160                         def    = X_Class_getClassDef( sClass );\r
161                         sClass = def.SuperClass;\r
162                         sFunc  = sClass.prototype[ name ];\r
163                         if( sFunc === func ){\r
164                                 hit = true; // 現在の関数にヒット\r
165                         } else\r
166                         if( hit && X_Object_inObject( name, this ) ){\r
167                                 if( X.Type.isFunction( sFunc ) ){\r
168                                         switch( args.length ){\r
169                                                 case 1 :\r
170                                                         return sFunc.call( this );\r
171                                                 case 2 :\r
172                                                         return sFunc.call( this, args[ 1 ] );\r
173                                                 case 3 :\r
174                                                         return sFunc.call( this, args[ 1 ], args[ 2 ] );\r
175                                                 case 4 :\r
176                                                         return sFunc.call( this, args[ 1 ], args[ 2 ], args[ 3 ] );\r
177                                                 default :\r
178                                                         args = X.Object.cloneArray( args );\r
179                                                         args.shift();\r
180                                                         return sFunc.apply( this, args );\r
181                                         };\r
182                                 };\r
183                                 break;\r
184                         };\r
185                 };\r
186         },\r
187         \r
188         /*\r
189          * TODO instanceof に対応したブラウザはそちらを使用\r
190          */\r
191         instanceOf : function( klass ){\r
192                 var Super = this;\r
193                 if( this.constructor === klass ) return true;\r
194                 while( Super = X_Class_getClassDef( Super ).SuperClass ){\r
195                         if( Super === klass ) return true;\r
196                 };\r
197                 return false;\r
198         }\r
199 };\r
200 \r
201 \r
202 // ------------------------------------------------------------------------- //\r
203 // --- interface ----------------------------------------------------------- //\r
204 // ------------------------------------------------------------------------- //\r
205 \r
206 /** @namespace */ \r
207 X.Class = {\r
208         \r
209         NONE         : 0,\r
210         \r
211     /**\r
212      * インスタンスは破棄時(this.kill())に回収され、次回の new MyClass() 時に再利用されます。\r
213      * @memberof X.Class */\r
214         POOL_OBJECT  :  1,\r
215         \r
216         /**\r
217          * 定義するクラスは抽象クラスになります。new AbstractClass() とするとエラーになります。\r
218          * @memberof X.Class */\r
219         ABSTRACT     :  2,\r
220         \r
221         \r
222         /** @memberof X.Class */\r
223         FINAL        :  4,\r
224         /** @memberof X.Class */\r
225         SUPER_ACCESS :  8,\r
226         /** @memberof X.Class */\r
227         PRIVATE_DATA : 16,\r
228         /** @memberof X.Class */\r
229         SINGLETON    : 32, // 未実装\r
230         \r
231         create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){\r
232                 var args        = X_Object_cloneArray( arguments ),\r
233                         displayName = args[ 0 ],\r
234                         classSetting,\r
235                         opt_pool, opt_abstract, opt_final, opt_private,\r
236                         privateDef,\r
237                         props,\r
238                         klass,\r
239                         classDef = {}, hash;\r
240                 if( X.Type.isString( displayName ) === true ){\r
241                         classDef.displayName = displayName;\r
242                         args.shift();\r
243                 };\r
244                 \r
245                 // クラス設定\r
246                 classDef.setting = classSetting = args[ 0 ];\r
247                 if( X.Type.isNumber( classSetting ) ){\r
248                         opt_pool     = !!( classSetting & X.Class.POOL_OBJECT  );\r
249                         opt_abstract = !!( classSetting & X.Class.ABSTRACT     );\r
250                         opt_final    = !!( classSetting & X.Class.FINAL        );\r
251                         opt_private  = !!( classSetting & X.Class.PRIVATE_DATA );\r
252                         if( opt_final && opt_abstract ){\r
253                                 X.Logger.critical( 'final & Abstract!' );\r
254                                 return;\r
255                         };      \r
256                         args.shift();\r
257                 } else {\r
258                         classDef.setting = 0;\r
259                 };\r
260                 \r
261                 // シャドウクラス\r
262                 if( X_Class_PRIVATE_CLASS_LIST.indexOf( args[ 0 ] ) !== -1 ){\r
263                         privateDef = X_Class_getClassDef( args[ 0 ] );\r
264                         if( privateDef.isPrivate !== true ){\r
265                                 X.Logger.critical( 'PrivateClass not found! please, X.Class.create( X.Class.PRIVATE, {...} ).' );\r
266                                 return;\r
267                         } else\r
268                         if( privateDef.Abstract === true ){\r
269                                 X.Logger.critical( 'PrivateClass is Abstract!' );\r
270                                 return;\r
271                         };\r
272                         classDef.privateClass = args.shift();\r
273                 };\r
274                 \r
275                 // インスタンスのメンバー\r
276                 props = args[ 0 ];\r
277                 if( !X.Type.isObject( props ) ){\r
278                         // サブクラスの場合、クラス定義の上書きがなくても作成可能\r
279                         // サブクラスでなくても、クラスメンバ用オブジェクトが無しでも作成可能\r
280                         //if( !X_Class_traits ){\r
281                         //      X.Logger.critical( 'No Class Def!' );\r
282                         //      return;\r
283                         //};\r
284                         props = {};\r
285                 } else\r
286                 if( props.Constructor && X.Type.isFunction( props.Constructor ) ){\r
287                         classDef.Constructor = props.Constructor;\r
288                 };\r
289 \r
290                 klass  = X_Callback_actualClosure( hash = { _ : X_Class_actualConstructor } ); // TODO hash = classDef\r
291                 hash.c = klass;\r
292                 klass.superClassOf = X_Class_superClassOf;\r
293                 klass.subClassOf   = X_Class_subClassOf;\r
294                 \r
295                 if( X_Class_useObjectCreate ){\r
296                         klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonProps, false );\r
297                         klass.prototype.constructor = klass;\r
298                 } else\r
299                 if( X_Class_use_proto_ ){\r
300                         X_Class_override( klass.prototype, props, true );\r
301                         if( X_Class_traits ){\r
302                                 klass.prototype.__proto__ = X_Class_traits;\r
303                         } else {\r
304                                 X_Class_override( klass.prototype, X_Class_CommonProps, false );\r
305                         };\r
306                 } else {\r
307                         klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonProps, false );\r
308                         klass.prototype.constructor = klass;\r
309                 };\r
310                 klass.name = displayName;\r
311                 \r
312                 if( opt_abstract ){\r
313                         classDef.Abstract = true;\r
314                 } else\r
315                 if( opt_pool ){\r
316                         classDef.pool = [];\r
317                         if( opt_private === false ) classDef.live = [];\r
318                 };                      \r
319                 if( opt_final ){\r
320                         classDef.Final = true;\r
321                 } else {\r
322                         klass.inherits = X_Class_inherits;\r
323                 };                      \r
324                 if( opt_private ){\r
325                         if( classDef.privateClass ){\r
326                                 X.Logger.critical( 'Private Data Class has no PrivateClass!' );\r
327                                 return;\r
328                         };\r
329                         classDef.isPrivate = true;\r
330                         X_Class_PRIVATE_CLASS_LIST.push( klass );\r
331                         X_Class_PRIVATE_DEF_LIST.push( classDef );\r
332                 } else {\r
333                         X_Class_CLASS_LIST.push( klass );\r
334                         X_Class_DEF_LIST.push( classDef );                              \r
335                 };\r
336                 return klass;\r
337         },\r
338         \r
339         _newPrivate  : X_Class_newPrivate,\r
340         \r
341         _getPrivate  : X_Class_getPrivate\r
342         \r
343 };\r
344 \r
345 // ------------------------------------------------------------------------- //\r
346 // --- implements ---------------------------------------------------------- //\r
347 // ------------------------------------------------------------------------- //\r
348 function X_Class_getClass( instance ){\r
349         var cList    = X_Class_CLASS_LIST,\r
350                 i        = cList.length,\r
351                 klass;\r
352         for( ; i; ){\r
353                 klass = cList[ --i ];\r
354                 if( instance.constructor === klass ) return klass;\r
355         };\r
356         cList = X_Class_PRIVATE_CLASS_LIST;\r
357         i     = cList.length;\r
358         for( ; i; ){\r
359                 klass = cList[ --i ];\r
360                 if( instance.constructor === klass ) return klass;\r
361         };\r
362         \r
363         if( cList.indexOf( instance ) !== -1 ) return instance;\r
364         if( X_Class_CLASS_LIST.indexOf( instance ) !== -1 ) return instance;\r
365 };\r
366 \r
367 function X_Class_getClassDef( KlassOrInstance ){\r
368         var i = X_Class_CLASS_LIST.indexOf( KlassOrInstance );\r
369         if( i === -1 ) i = X_Class_CLASS_LIST.indexOf( X_Class_getClass( KlassOrInstance ) );\r
370         if( i !== -1 ) return X_Class_DEF_LIST[ i ];\r
371         \r
372         i = X_Class_PRIVATE_CLASS_LIST.indexOf( KlassOrInstance );\r
373         if( i === -1 ) i = X_Class_PRIVATE_CLASS_LIST.indexOf( X_Class_getClass( KlassOrInstance ) );\r
374         if( i !== -1 ) return X_Class_PRIVATE_DEF_LIST[ i ];\r
375         \r
376         if( X_Class_DEF_LIST.indexOf( KlassOrInstance ) !== -1 ) return KlassOrInstance;\r
377         if( X_Class_PRIVATE_DEF_LIST.indexOf( KlassOrInstance ) !== -1 ) return KlassOrInstance;\r
378 };\r
379 \r
380 function X_Class_newPrivate( /* instance, args */ ){\r
381         var args         = X_Object_cloneArray( arguments ),\r
382                 user         = args.shift(),\r
383                 def          = X_Class_getClassDef( user ),\r
384                 privateClass = def.privateClass,\r
385                 privateDef   = X_Class_getClassDef( privateClass ),\r
386                 i            = -1;\r
387         if( def.userList ){\r
388                 i = def.userList.indexOf( user );\r
389         } else {\r
390                 def.userList = [];\r
391                 def.dataList = [];\r
392         };\r
393         if( i !== -1 ){\r
394                 X.Logger.critical( 'PrivateData already exist!' );\r
395                 return;\r
396         };\r
397         if( privateDef._tempUser ){\r
398                 X.Logger.critical( 'newPrivate を連続呼び出しされたところ破綻' );\r
399                 return;\r
400         };\r
401         privateDef._tempUser = user;\r
402         return X_Class_actualConstructor( privateClass( X_Closure_COMMAND_BACK ), args );// privateClass.__new( args );\r
403 };\r
404 \r
405 function X_Class_getPrivate( instance ){\r
406         var def = X_Class_getClassDef( instance ),\r
407                 i   = def.userList.indexOf( instance );\r
408         if( i !== -1 ) return def.dataList[ i ];\r
409 };\r
410 \r
411 /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */\r
412 function X_Class_override( target, src, force ){\r
413         var p;\r
414         for( p in src ){\r
415                 if( p === '__proto__' || p === 'prototype' || p === 'constructor' ){\r
416                         X.Logger.critical( p + ' is reserved!' );\r
417                         return;\r
418                 };\r
419                 if( force || target[ p ] === void 0 ){\r
420                         target[ p ] = src[ p ];\r
421                 };\r
422         };\r
423         return target;\r
424 };\r
425 \r
426 function X_Class_superClassOf( klass ){\r
427         var myDef      = X_Class_getClassDef( this ),\r
428                 targetDef  = X_Class_getClassDef( klass ),\r
429                 SuperClass = klass;\r
430 \r
431         if( !myDef || !targetDef || this === klass ) return false;\r
432         \r
433         while( SuperClass = X_Class_getClassDef( SuperClass ).SuperClass ){\r
434                 if( SuperClass === this ) return true;\r
435         };\r
436         \r
437         return false;\r
438 };\r
439 \r
440 function X_Class_subClassOf( klass ){\r
441         return X_Class_superClassOf.call( klass, this );\r
442 };\r
443         \r
444 /* サブクラスを作るメソッド  \r
445  * var subClass = superClass.inherits( ... ) \r
446  * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002\r
447  */\r
448 function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props */ ){\r
449         var args        = X_Object_cloneArray( arguments ),\r
450                 params      = [],\r
451                 Super       = this,\r
452                 superDef    = X_Class_getClassDef( Super ),\r
453                 displayName = args[ 0 ],\r
454                 classSetting,\r
455                 //opt_super,\r
456                 klass, def;\r
457         if( superDef.Final ) X.Logger.critical( 'X.Class inherits, Class is final!' );\r
458         \r
459         // サブクラス名\r
460         if( X.Type.isString( displayName ) ){\r
461                 args.shift();\r
462         } else {\r
463                 displayName = 'SubClass of ' + superDef.displayName;\r
464         };\r
465         params.push( displayName );\r
466         \r
467         // サブクラス設定\r
468         classSetting = args[ 0 ];\r
469         if( X.Type.isNumber( classSetting ) ){\r
470                 args.shift();\r
471         } else {\r
472                 // クラス設定がない場合、親からコピーして、Abstract flag は落とす??\r
473                 classSetting = superDef.setting;// &= ~X.Class.ABSTRACT;\r
474         };\r
475         if( superDef.isPrivate ) classSetting = classSetting | X.Class.PRIVATE_DATA;\r
476         //opt_super = !!( classSetting & X.Class.SUPER_ACCESS );\r
477         params.push( classSetting );\r
478 \r
479         // サブクラスのシャドウ\r
480         if( args[ 0 ] && X_Class_getClass( args[ 0 ] ) ){\r
481                 params.push( args.shift() );\r
482         } else\r
483         if( superDef.privateClass ){\r
484                 params.push( superDef.privateClass );\r
485         };\r
486         \r
487         /* props 未定義でも可 */\r
488         params.push( args[ 0 ] );\r
489         \r
490         // 継承クラスの作成\r
491         if( X_Class_useObjectCreate ){\r
492                 X_Class_traits = Object.create( Super.prototype );\r
493         } else\r
494         if( X_Class_use_proto_ ){\r
495                 X_Class_traits = Super.prototype;\r
496         } else {\r
497                 X_Class_traits = new Super( X_Closure_COMMAND_DROP );\r
498         };\r
499         klass  = X.Class.create.apply( X.Class, params );\r
500         X_Class_traits = null;\r
501         \r
502         def    = X_Class_getClassDef( klass );\r
503         // 継承用プロパティを控える\r
504         //if( opt_super === true ){\r
505                 //def.superAccess = true;\r
506                 def.SuperClass  = Super;\r
507                 def.SuperProto  = Super.prototype;\r
508                 def.SuperConstructor = superDef.Constructor || superDef.SuperConstructor;\r
509         // else {\r
510         //      def.SuperClass = Super; // instanceOf() で親クラスを調べる!\r
511         //};\r
512         \r
513         return klass;\r
514 };\r
515         \r
516 /*\r
517  * new の実体.コンストラクタの機能は instance.Constructor に書く.\r
518  * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる\r
519  */\r
520 function X_Class_actualConstructor( obj, args ){\r
521         var klass    = obj.c,//this,\r
522                 def      = X_Class_getClassDef( klass ),\r
523                 dataUser = def._tempUser,\r
524                 instance, obj,\r
525                 userDef;\r
526         if( def.Abstract ){\r
527                 X.Logger.critical( 'AbstractClass!' );\r
528                 return;\r
529         };\r
530         if( def.isPrivate && !dataUser ){\r
531                 X.Logger.critical( 'use myClass.newPrivate( instance, ...args )!' );\r
532                 return;\r
533         };\r
534         \r
535         instance = def.pool && def.pool.length > 0 ?\r
536                                         def.pool.pop() :\r
537                                 X_Class_useObjectCreate ?\r
538                                         Object.create( klass.prototype ) :\r
539                                         new klass( X_Closure_COMMAND_DROP );\r
540         \r
541         if( def.isPrivate ){\r
542                 userDef = X_Class_getClassDef( dataUser );\r
543                 userDef.dataList.push( instance );\r
544                 userDef.userList.push( dataUser );\r
545                 instance.User = dataUser;\r
546                 def._tempUser = null;\r
547         } else {\r
548                 def.live && def.live.push( instance );\r
549         };\r
550         //if( def.superAccess ){\r
551                 // TODO klass.prototype に移動\r
552                 //instance.Super = def.SuperProto;\r
553                 //instance.SuperConstructor = X_Class_superConstructor;\r
554         //};\r
555         obj = def.Constructor ?\r
556                         def.Constructor.apply( instance, args ) :\r
557                 def.SuperConstructor &&\r
558                         def.SuperConstructor.apply( instance, args );\r
559         if( ( X.Type.isObject( obj ) && obj !== instance ) || X.Type.isFunction( obj ) ){ // Class\r
560                 instance.kill();\r
561                 return obj;\r
562         };\r
563         return instance;\r
564 };\r
565 \r
566 console.log( 'X.Core.Class' );\r