OSDN Git Service

実ゆっくりに向きを追加。次回は左向きのときの座標あわせを行う。TODO要確認
[yukkurioverwint/YukkuriOverwinter.git] / mixing.enchant.js
1 /**
2  * @fileOverview
3  * mixing.enchant.js
4  [lang:ja]
5  * <p>複数のクラスを混ぜることができるようにし、同じ関数やプロパティを複数のクラスに追加することができるようにするenchant.jsプラグイン.
6  * その上、コピーアンドペーストをしないために、製法({@link enchant.Class.MixingRecipe})で定義された関数やプロパティを
7  * 複数クラスに混ぜることもできるようにする.</p>
8  * <p>これで複数の継承ようなことができるということ</p>
9  * <p>必要なもの:</p><ul>
10  * <li>enchant.js v0.6 以上.</li></ul></p>
11  * 詳細は{@link enchant.Class.mixClasses}, {@link enchant.Class.MixingRecipe.createFromClass},
12  * {@link enchant.Class.mixClassesFromRecipe}, {@link enchant.Class.MixingRecipe} や
13  * {@link enchant.Class.applyMixingRecipe} 参照してください.
14  [/lang]
15  [lang:en]
16  * <p>A plugin for enchant.js which allows to mix 
17  * arbitrary many {@link enchant.Class} classes together.
18  * It is also possible to add functions and properties defined
19  * as a recipe ({@link enchant.Class.MixingRecipe}) to arbitrary many classes to avoid copy and paste.</p>
20  * <p>Through this it is possible to achieve a behavior similar to multiple inheritance</p>
21  * <p>Requires:<ul>
22  * <li>enchant.js v0.6 or later.</li></ul></p>
23  * See also {@link enchant.Class.mixClasses}, {@link enchant.Class.MixingRecipe.createFromClass}, 
24  * {@link enchant.Class.mixClassesFromRecipe}, {@link enchant.Class.MixingRecipe} and 
25  * {@link enchant.Class.applyMixingRecipe} for an introduction.
26  [/lang]
27  [lang:de]
28  * <p>Ein Plugin für enchant.js mit dem es möglich ist, beliebig viele
29  * {@link enchant.Class} Klassen zusammen zu mischen.
30  * Um Copy & Paste zu vermeiden, ist es auch möglich Funktionen und
31  * Properties, die in einem Rezept ({@link enchant.Class.MixingRecipe}) 
32  * definiert sind zu beliebig vielen Klassen hinzuzufügen.</p>
33  * <p>Durch dies ist es möglich ein Verhalten ähnlich zu multipler Vererbung zu erlangen.</p>
34  * <p>Benötigt:<ul>
35  * <li>enchant.js v0.6 oder höher.</li></ul></p>
36  * Weiterführende Informationen: {@link enchant.Class.mixClasses}, {@link enchant.Class.MixingRecipe.createFromClass}, 
37  * {@link enchant.Class.mixClassesFromRecipe}, {@link enchant.Class.MixingRecipe} und 
38  * {@link enchant.Class.applyMixingRecipe}
39  [/lang]
40  * @require enchant.js v0.6+
41  *
42  * @version 0.1
43  * @author Ubiquitous Entertainment Inc. (Kevin Kratzer)
44  **/
45
46 if (enchant !== undefined) {
47     (function() {
48
49         /**
50          * @private
51          */
52         var decorateFunctionFactory = function(srcFunction, currentFunctionName) {
53             return function() {
54                 var firstResult, secondResult;
55                 firstResult = this._mixing[currentFunctionName].apply(this,arguments);
56                 secondResult = srcFunction.apply(this,arguments);
57                 if(secondResult) {
58                     return secondResult;
59                 }
60                 if(firstResult) {
61                     return firstResult;
62                 }
63             };
64         };
65
66         /**
67          * @private
68          */
69         var voidFunction = function(){};
70
71         /**
72          * @private
73          */
74         var multipleMixingCombinationFunctionFactory = function(oldFunc,newFunc, key) {
75             return function() {
76                 var firstResult = oldFunc.apply(this,arguments);
77                 var mixingStore = this._mixing[key];
78                 this._mixing[key] = voidFunction;
79                 var secondResult = newFunc.apply(this,arguments);
80                 this._mixing[key] = mixingStore;
81                 if(secondResult) {
82                     return secondResult;
83                 }
84                 if(firstResult) {
85                     return firstResult;
86                 }
87             };
88         };
89
90         /**
91          * @private
92          */
93         var createFromPrototypeNonRecursive = function(decorate, override, properties, source, functionOverrideNameList, functionIgnoreNameList, propertyIgnoreNameList) {
94             for(var key in source) {
95                 if(source.hasOwnProperty(key)) {
96                     var descriptor = Object.getOwnPropertyDescriptor(source, key);
97                     if(descriptor.value && typeof(descriptor.value) === 'function') {
98                         if((!functionIgnoreNameList || functionIgnoreNameList.indexOf(key) === -1) && key !== 'constructor') {
99                             if(!functionOverrideNameList || functionOverrideNameList.indexOf(key) === -1) {
100                                 decorate[key] = (decorateFunctionFactory(source[key],key));
101                             } else {
102                                 override[key] = source[key];
103                             }
104                         }
105                     } else {
106                         if(!propertyIgnoreNameList || propertyIgnoreNameList.indexOf(key) === -1 && key !== '_mixing') {
107                             properties[key] = descriptor;
108                         }
109                     }
110                 }
111             }
112         };
113
114         /**
115          * @private
116          */
117         var createFromPrototype = function(decorate,override,properties,source,onlyOwnProperties, functionOverrideNameList, functionIgnoreNameList, propertyIgnoreNameList) {
118             if(!onlyOwnProperties && source instanceof Object) {
119                 createFromPrototype(decorate,override,properties,Object.getPrototypeOf(source),onlyOwnProperties, functionOverrideNameList, functionIgnoreNameList, propertyIgnoreNameList);
120             }
121             createFromPrototypeNonRecursive(decorate,override,properties,source, functionOverrideNameList, functionIgnoreNameList, propertyIgnoreNameList);
122         };
123
124         /**
125          * @private
126          */
127         var getFunctionParams = function(methodString) {
128             if(typeof(methodString) !== 'string') {
129                 methodString = methodString.toString();
130             }
131             return methodString.substring(methodString.indexOf('(')+1,methodString.indexOf(')')).replace(/\s+/,'').split(',');
132         };
133
134         /*Public Interface */
135         /**
136          * @scope enchant.Class.MixingRecipe.prototype
137          */
138         enchant.Class.MixingRecipe = enchant.Class.create({
139             /**
140             [lang:ja]
141              * 混ぜる中、どういう風に関数やプロパティが追加されるか設定する新たなMixingRecipeを生成する.
142              * クラスからMixingRecipeを生成することには {@link enchant.Class.MixingRecipe.createFromClass} を参照してください.
143              * @class 混ぜる先にどういう風に混ぜる処理を行うか設定する.
144              * このために、MixingRecipeはプロパティが三つある:
145              * <ul><li>decorateMethods(先の関数をラップする関数、デコレータ・パターンを参照してください)</li>
146              * <li>overrideMethods (先の関数をオーバーライドする関数)</li>
147              * <li>overrideProperties (先のプロパティをオーバーライドするプロパティ)</li></ul>
148              * <p>{@link enchant.Class.mixClasses}、 {@link enchant.Class.mixClassesFromRecipe} や {@link enchant.Class.applyMixingRecipe} を参照してください.</p>
149              * @param {Object} decorateMethods 先の関数をラップする関数、デコレータ・パターンを参照してください. 混ぜる結果のクラスでラップされた関数をアクセスするように_mixingというプロパティがある、例:this._mixing.myFunction.apply(this,arguments).<br>(キーと値のペア持っているオブジェクト、キーは関数名、値は関数).
150              * @param {Object} overrideMethods 先の関数をオーバーライドする関数.<br>(キーと値のペア持っているオブジェクト、キーは関数名、値は関数).
151              * @param {Object} properties 先のプロパティをオーバーライドするプロパティ.<br>(キーと値のペア持っているオブジェクト、キーは関数名、値はプロパティデスクリプタ).
152              * @property {Object} decorateMethods 先の関数をラップする関数、デコレータ・パターンを参照してください. 混ぜる結果のクラスでラップされた関数をアクセスするように_mixingというプロパティがある、例:this._mixing.myFunction.apply(this,arguments).<br>(キーと値のペア持っているオブジェクト、キーは関数名、値は関数).
153              * @property {Object} overrideMethods 先の関数をオーバーライドする関数.<br>(キーと値のペア持っているオブジェクト、キーは関数名、値は関数).
154              * @property {Object} overrideProperties 先のプロパティをオーバーライドするプロパティ.<br>(キーと値のペア持っているオブジェクト、キーは関数名、値はプロパティデスクリプタ).
155             [/lang]
156             [lang:en]
157              * Creates a new MixingRecipe which is used for describing in which way functions and properties should be added during the mixing.
158              * To create a recipe from an existing class see {@link enchant.Class.MixingRecipe.createFromClass}
159              * @class This class is describing in which way the mixing will be performed on the target classes.
160              * For this purpose, MixingRecipe contains three properties:
161              * <ul><li>decorateMethods (methods which will be decorated in the target, see decorator pattern)</li>
162              * <li>overrideMethods (methods which will be overriden in the target)</li>
163              * <li>overrideProperties (properties which will be redefined in the target)</li></ul>
164              * <p>See also {@link enchant.Class.mixClasses}, {@link enchant.Class.mixClassesFromRecipe} and {@link enchant.Class.applyMixingRecipe}.</p>
165              * @param {Object} decorateMethods The methods which will be decorated in the target, see decorator pattern. To access methods which have been decorated in the class resulting from mixing the _mixing property can be used, e.g. this._mixing.myFunction.apply(this,arguments).<br>(Object containing key-value pairs, key := function name, value := function).
166              * @param {Object} overrideMethods The methods which will be overriden in the target.<br>(Object containing key-value pairs, key := function name, value := function).
167              * @param {Object} properties The properties which will be redefined in the target.<br>(Object containing key-value pairs, key := function name, value := property descriptor).
168              * @property {Object} decorateMethods The methods which will be decorated in the target, see decorator pattern. To access methods which have been decorated in the class resulting from mixing the _mixing property can be used, e.g. this._mixing.myFunction.apply(this,arguments).<br>(Object containing key-value pairs, key := function name, value := function).
169              * @property {Object} overrideMethods The methods which will be overriden in the target.<br>(Object containing key-value pairs, key := function name, value := function).
170              * @property {Object} overrideProperties The properties which will be redefined in the target.<br>(Object containing key-value pairs, key := function name, value := property descriptor).
171             [/lang]
172             [lang:de]
173              * Erstellt ein neues MixingRecipe, welches beschreibt, auf welche Art und Weise Funktionen und Properties während des Mischens hinzugefügt werden.
174              * Um ein Rezept aus einer bereits existierend Klasse zu erstellen, ist auf {@link enchant.Class.MixingRecipe.createFromClass} zu verweisen.
175              * @class Diese Klasse beschreibt auf welche Art und Weise das mischen mit der Zielklasse durchgeführt wird.
176              * Für diesen Zweck enthählt ein MixingRecipe drei Properties:
177              * <ul><li>decorateMethods (Methoden, welche in der Zielklasse dekoriert werden, siehe Dekorierer Entwurfsmuster)</li>
178              * <li>overrideMethods (Methoden, welche in der Zielklasse überschrieben werden)</li>
179              * <li>overrideProperties (Properties, welche in der Zielklasse redefiniert werden)</li></ul>
180              * <p>Siehe auch: {@link enchant.Class.mixClasses}, {@link enchant.Class.mixClassesFromRecipe} und {@link enchant.Class.applyMixingRecipe}.</p>
181              * @param {Object} decorateMethods Die Methoden, welche in der Zielklasse dekoriert werden, siehe Dekorierer Entwurfsmuster. Auf die dekoriertie Methode kann in der durch das Mixen erstellten Klasse mit Hilfe des _mixing Property zugegriffen werden, z.B. this._mixing.myFunction.apply(this,arguments).<br>(Objekt welches Schlüssel-Wert Paare enthält, Schlüssel := Funktionsname, Wert := Funktion)
182              * @param {Object} overrideMethods Die Methoden, welche in der Zielklasse überschrieben werden.<br>(Objekt welches Schlüssel-Wert Paare enthält, Schlüssel := Funktionsname, Wert := Funktion).
183              * @param {Object} properties Die Properties, welche in der Zielklasse redefiniert werden.<br>(Objekt welches Schlüssel-Wert Paare enthält, Schlüssel := Funktionsname, Wert := Propertydescriptor).
184              * @property {Object} decorateMethods Die Methoden, welche in der Zielklasse dekoriert werden, siehe Dekorierer Entwurfsmuster. Auf die dekoriertie Methode kann in der durch das Mixen erstellten Klasse mit Hilfe des _mixing Property zugegriffen werden, z.B. this._mixing.myFunction.apply(this,arguments).<br>(Objekt welches Schlüssel-Wert Paare enthält, Schlüssel := Funktionsname, Wert := Funktion)
185              * @property {Object} overrideMethods Die Methoden, welche in der Zielklasse überschrieben werden.<br>(Objekt welches Schlüssel-Wert Paare enthält, Schlüssel := Funktionsname, Wert := Funktion).
186              * @property {Object} overrideProperties Die Properties, welche in der Zielklasse redefiniert werden.<br>(Objekt welches Schlüssel-Wert Paare enthält, Schlüssel := Funktionsname, Wert := Propertydescriptor).
187             [/lang]
188              * @example
189              *      var recipe = new enchant.Class.MixingRecipe({
190              *          add : function(value) {
191              *              this._myValue += 3*value;
192              *              this._mixing.add.apply(this,arguments);
193              *          },
194              *          mult : function(value) {
195              *              this._myValue *= value*7;
196              *              this._mixing.mult.apply(this,arguments);
197              *          }
198              *      },{
199              *          sub : function(value) {
200              *              this._myValue -= 5*value;
201              *          }
202              *      },{
203              *      myProperty : {
204              *          get: function() {
205              *              return 3*this._myPropertyValue;
206              *          },
207              *          set : function(val) {
208              *              this._myPropertyValue = val;
209              *          }
210              *      }});
211              *      var NewClass = enchant.Class.applyMixingRecipe(Class1,recipe);
212              * @extends Object
213              * @constructs
214              */
215             initialize : function(decorateMethods, overrideMethods, properties) {
216                 this.decorateMethods = decorateMethods;
217                 this.overrideMethods = overrideMethods;
218                 this.overrideProperties = properties;
219             }
220         });
221
222         /**
223          [lang:ja]
224          * 引数のクルスの関数やプロパティから、MixingRecipeを生成する.
225          * デフォルト振舞はsourceClassの全ての関数やプロパティ、スーパークラスの関数やプロパティも使用して、
226          * 混ぜる先の関数をラップする(decorate).<br>_mixingプロパティでラップされた関数が自動的に、
227          * sourceClassと混ぜる先の関数を呼び出されるので、関係なくてもいい.
228          * <p>対応引数でデフォルト振舞を変更ができる.</p>
229          * 
230          * @param {Function<constructor enchant.Classで生成された関数>} sourceClass このクラスから、MixingRecipeが生成される.
231          * @param [boolean] onlyOwnProperties Trueの場合、スーパークラスの関数やプロパティが無視されない. 
232          * @param [Array<String>] functionOverrideNameList 混ぜるときオーバーライドされる関数名を持っている配列.  
233          * @param [Array<String>] functionIgnoreNameList MixingRecipeを生成するとき無視される関数名を持っている配列.  
234          * @param [Array<String>] propertyIgnoreNameList MixingRecipeを生成するとき無視されるプロパティ名を持っている配列.
235          * @returns {enchant.Class.MixingRecipe} クラス定義から生成されたMixingRecipe.
236          [/lang]
237          [lang:en]
238          * Takes the methods and properties of the given class to create a new MixingRecipe.
239          * The default behavior is to take all functions and properties of the given class
240          * including functions and properties defined in super classes, whereas functions
241          * are set to decorate the mixing target.<br>Methods which are decorated will automatically
242          * call the soureClass method and the mixing target method (using the _mixing property) - 
243          * so there is no need to handle this yourself.
244          * <p>To change the default behavior set the corresponding arguments of the function.</p>
245          * 
246          * @param {Function<constructor function created with enchant.Class>} sourceClass The class which will be used to create the recipe.
247          * @param [boolean] onlyOwnProperties If set to true, the functions and properties of the super classes will be ignored.
248          * @param [Array<String>] functionOverrideNameList An array containing names of functions which should be set to override functions in the target during mixing.
249          * @param [Array<String>] functionIgnoreNameList An array containing names of functions which should be ignored when creating the recipe.
250          * @param [Array<String>] propertyIgnoreNameList An array containing names of properties which should be ignored when creating the recipe.
251          * @returns {enchant.Class.MixingRecipe} The MixingRecipe created from the definition of the sourceClass.
252          [/lang]
253          [lang:de]
254          * Nimmt die Methoden und Properties der übergebenen Klasse um ein neues MixingRecipe zu erstellen.
255          * Das Standardverhalten dabei ist, alle Funktionen und Properties der übergebenen Klasse, 
256          * einschließlich der Funktionen und Properties in den Superklassen zu nehmen und diese
257          * in der Zielklasse beim mixen zu dekorieren.<br>Methoden welche dekoriert werden, rufen
258          * automatisch die Methoden der sourceClass und der Zielklasse des Mixens, mit Hilfe des
259          * _mixing Properties, auf. Daher muss dies nicht selbst berücksichtigt werden.
260          * <p>Durch die entsprechenden Argumente der Funktion kann das Standardverhalten zu verändert werden.</p>
261          * 
262          * @param {Function<constructor Funktion die mit enchant.Class erstellt wurde>} sourceClass Die Klasse aus der das MixingRecipe erstellt wird.
263          * @param [boolean] onlyOwnProperties Wenn dieses Argument true ist, werden Funktionen und Properties der Superklassen ignoriert. 
264          * @param [Array<String>] functionOverrideNameList Ein Array welches Namen von Funktionen enthält, welche während des Mixens überschrieben werden sollen. 
265          * @param [Array<String>] functionIgnoreNameList Ein Array welches Namen von Funktionen enthält, welche bei der MixingRecipe erstellung ignoriert werden sollen. 
266          * @param [Array<String>] propertyIgnoreNameList Ein Array welches Namen von Properties enthält, welche bei der MixingRecipe erstellung ignoriert werden sollen.
267          * @returns {enchant.Class.MixingRecipe} Das MixingRecipe, welches aus der Definition der sourceClass erstellt wurde.
268          [/lang]
269          * @example
270          *      var recipe = enchant.Class.MixingRecipe.createFromClass(Class2, true, 
271          *              ['overrideFunction1','overrideFunction2'],
272          *              ['ignoreFunction1','ignoreFunction2'],
273          *              ['ignoreProperty1','ignorePropterty2']);
274          *      recipe.overrideMethods['additionalFunction'] = new function() {
275          *          console.log('Hello, World');
276          *      }
277          *      recipe.overrideProperties['newProperty'] = {
278          *          get: function() {
279          *              return this._newProperty;
280          *          },
281          *          set : function(val) {
282          *              this._newProperty = val;
283          *          }
284          *      }
285          *      var NewClass = enchant.Class.mixClassesFromRecipe(Class1,Class2,recipe);
286          * @constructs
287          * @static
288          */
289         enchant.Class.MixingRecipe.createFromClass = function(sourceClass, onlyOwnProperties, functionOverrideNameList, functionIgnoreNameList, propertyIgnoreNameList) {
290             var decorate = {};
291             var override = {};
292             var properties = {};
293
294             var source = sourceClass.prototype;
295             createFromPrototype(decorate,override,properties,source,onlyOwnProperties, functionOverrideNameList, functionIgnoreNameList, propertyIgnoreNameList);
296             return new enchant.Class.MixingRecipe(decorate,override,properties);
297         };
298
299         /**
300          [lang:ja]
301          * 設定されたMixingRecipeを使用して、firstClassというクラスに実行して、この結果を戻る。設定されたMixingRecipeはsecondClassというクラスに関係があったほうがいい.
302          * どちらでもクラスの初期化関数を呼び出すデフォルト初期化関数が追加される.
303          * このデフォルト初期か関数の書式は:<br>
304          * ([firstClass コンストラクタ 引数 1],...,[firstClass コンストラクタ 引数 n],[secondClass コンストラクタ 引数 1],...[secondClass コンストラクタ 引数 n])</p>
305          * <p>どちらでもクラスが変更されない</p>{@link enchant.Class.MixingRecipe} を参照してください.
306          * @param {Function<constructor enchant.Classで生成された関数>} firstClass MixingRecipeを実行されるクラス.
307          * @param {Function<constructor enchant.Classで生成された関数>} sourceClass MixingRecipに関係があるクラス。デフォルト初期化関数に使用される。
308          * @param {enchant.Class.MixingRecipe} recipe firstClassに実行される製法。 secondClassに関係があったほうがいい.
309          * @param [Function] initializeMethod 設定すると、新しいクラスの初期化にデフォルト初期化関数が使用されないけど、この関数が使用される. 
310          * @returns {Function<constructor enchant.Classで生成された関数>} 製法でどちらでもクラスを混ぜた結果クラス.
311          [/lang]
312          [lang:en]
313          * Uses the given MixingRecipe, applies it to the first class and returns the result - the MixingRecipe should correspond to the secondClass.
314          * A default initialize method will be added which will call the initialize functions of both classes.
315          * The signature for the default initialize method is:<br>
316          * ([firstClass constructor arg 1],...,[firstClass constructor arg n],[secondClass constructor arg1],...[secondClass constructor arg n])
317          * <p>Both classes will not be modified.</p> See also: {@link enchant.Class.MixingRecipe}
318          * 
319          * @param {Function<constructor function created with enchant.Class>} firstClass The class to which the recipe will be applied.
320          * @param {Function<constructor function created with enchant.Class>} secondClass The class which is related to the MixingRecipe, used for the default initialize function.
321          * @param {enchant.Class.MixingRecipe} recipe The recipe which is applied to the first class - should correspond to the secondClass. 
322          * @param [Function] initializeMethod If provided, this function will be used to initialize the resulting class instead of the default initialize method.
323          * @returns {Function<constructor function created with enchant.Class>} initializeMethod The class which is the result of mixing both classes using the recipe.
324          [/lang]
325          [lang:de]
326          * Nutzt das gegebene MixingRecipe, wendet es auf die "firstClass" Klasse an und liefert das Ergebnis daraus zurück - das MixingRecipe sollte der secondClass entsprechen.
327          * Eine Standard-Initialisierungsmethode wird hinzugefügt, welche die Initialisierungsmethode beider Klassen aufruft.
328          * Die Signatur für diese Standard-Initialisierungsmethode ist:<br>
329          * ([firstClass Konstruktor Arg 1],...,[firstClass Konstruktor Arg n],[secondClass Konstruktor Arg 1],...[secondClass Konstruktor Arg n])</p>
330          * <p>Beide Klassen werden nicht verändert.</p> Siehe auch: {@link enchant.Class.MixingRecipe}
331          * @param {Function<constructor Funktion die mit enchant.Class erstellt wurde>} firstClass Die Klasse auf die das MixingRecipe angewendet wird.
332          * @param {Function<constructor Funktion die mit enchant.Class erstellt wurde>} secondClass Die Klasse die dem MixingRecipe entpsricht, wird für die Standard-Initialisierungsmethode genutzt.
333          * @param {enchant.Class.MixingRecipe} recipe Das MixingRecipe, welches auf die firstClass Klasse angewendet wird - sollte der secondClass entsprechen.
334          * @param [Function] initializeMethod Falls gegeben, wird diese Methode, anstelle der Standard-Initialisierungsmethode, zum Initialisieren der resultierenden Klasse verwendet. 
335          * @returns {Function<constructor Funktion die mit enchant.Class erstellt wurde>} Die Klasse, welche das Ergebnis des Mixens beider Klassen mit Hilfe des MixingRecipe darstellt.
336          [/lang]
337          * @example
338          *      var MapGroup = enchant.Class.mixClasses(Map, Group,true);
339          *      var map = new MapGroup(16, 16);
340          *      var SpriteLabel = enchant.Class.mixClasses(Sprite, Label,true);
341          *      var kumaLabel = new SpriteLabel(32,32,'Kuma');
342          * @static
343          */
344         enchant.Class.mixClassesFromRecipe = function(firstClass, secondClass, recipe, initializeMethod) {
345             var result = enchant.Class.applyMixingRecipe(firstClass,recipe);
346             var paramLength = getFunctionParams(firstClass.prototype.initialize).length;
347             if(typeof(initializeMethod) !== 'function') {
348                 initializeMethod = function() {
349                     var args = Array.prototype.slice.call(arguments);
350                     secondClass.prototype.initialize.apply(this,args.slice(paramLength));
351                     firstClass.prototype.initialize.apply(this,args.slice(0,paramLength));
352                 };
353             }
354             result.prototype.initialize = initializeMethod;
355             return result;
356         };
357
358
359         /**
360          [lang:ja]
361          * secondClassというクルスからMixingRecipeを生成して、firstClassというクラスに実行して、この結果を戻る.
362          * デフォルト振舞はsecondClassの全ての関数やプロパティ、スーパークラスの関数やプロパティも使用して、
363          * 混ぜる先の関数をラップする(decorate).<br>_mixingプロパティでラップされた関数が自動的に、
364          * sourceClassと混ぜる先の関数を呼び出されるので、関係なくてもいい.
365          * <p>その上、どちらでもクラスの初期化関数を呼び出すデフォルト初期化関数が追加される.このデフォルト初期か関数の書式は:<br>
366          * ([firstClass コンストラクタ 引数 1],...,[firstClass コンストラクタ 引数 n],[secondClass コンストラクタ 引数 1],...[secondClass コンストラクタ 引数 n])</p>
367          * <p>どちらでもクラスが変更されない</p>{@link enchant.Class.MixingRecipe} を参照してください.
368          * @param {Function<constructor enchant.Classで生成された関数>} firstClass MixingRecipeを実行されるクラス.
369          * @param {Function<constructor enchant.Classで生成された関数>} sourceClass このクラスから、MixingRecipeが生成される.
370          * @param [boolean] onlyOwnProperties Trueの場合、スーパークラスの関数やプロパティが無視されない. 
371          * @param [Function] initializeMethod 設定すると、新しいクラスの初期化にデフォルト初期化関数が使用されないけど、この関数が使用される. 
372          * @returns {Function<constructor enchant.Classで生成された関数>} どちらでもクラスを混ぜた結果クラス.
373          [/lang]
374          [lang:en]
375          * Creates an MixingRecipe out of the second class, applies it to the first class and returns the result.
376          * The default behavior is to take all functions and properties of the second class,
377          * including functions and properties defined in its super classes, whereas functions
378          * are set to decorate the mixing target.<br>Methods which are decorated will automatically
379          * call the soureClass method and the mixing target method (using the _mixing property) - 
380          * so there is no need to handle this yourself.
381          * <p>Furthermore, a default initialize method will be added which will
382          * call the initialize functions of both classes. The signature for the default initialize method is:<br>
383          * ([firstClass constructor arg 1],...,[firstClass constructor arg n],[secondClass constructor arg 1],...[secondClass constructor arg n])</p>
384          * <p>Both classes will not be modified.</p> See also: {@link enchant.Class.MixingRecipe}
385          * 
386          * @param {Function<constructor function created with enchant.Class>} firstClass The class to which the recipe will be applied.
387          * @param {Function<constructor function created with enchant.Class>} secondClass The class from which the recipe will be created
388          * @param [boolean] useOnlyOwnPropertiesForSecondClass If set to true, the functions and properties of the super classes will be ignored during the recipe creation of the secondClass.
389          * @param [Function] initializeMethod If provided, this function will be used to initialize the resulting class instead of the default initialize method.
390          * @returns {Function<constructor function created with enchant.Class>} The class which is the result of mixing both classes.
391          [/lang]
392          [lang:de]
393          * Erstellt ein MixingRecipe aus der "secondClass" Klasse, wendet dieses auf die "firstClass" Klasse an und liefert das Ergebnis daraus zurück.
394          * Das Standardverhalten dabei ist, alle Funktionen und Properties der "secondClass" Klasse, 
395          * einschließlich der Funktionen und Properties in deren Superklassen zu nehmen und diese
396          * in der Zielklasse beim mixen zu dekorieren.<br>Methoden welche dekoriert werden, rufen
397          * automatisch die Methoden der sourceClass und der Zielklasse des Mixens, mit Hilfe des
398          * _mixing Properties, auf. Daher muss dies nicht selbst berücksichtigt werden.
399          * <p>Des Weiteren wird eine Standard-Initialisierungsmethode, welche die Initialisierungsmethode beider Klassen aufruft, hinzugefügt.
400          * Die Signatur für diese Standard-Initialisierungsmethode ist:<br>
401          * ([firstClass Konstruktor Arg 1],...,[firstClass Konstruktor Arg n],[secondClass Konstruktor Arg 1],...[secondClass Konstruktor Arg n])</p>
402          * <p>Beide Klassen werden nicht verändert.</p> Siehe auch: {@link enchant.Class.MixingRecipe}
403          * 
404          * @param {Function<constructor Funktion die mit enchant.Class erstellt wurde>} firstClass Die Klasse auf die das MixingRecipe angewendet wird.
405          * @param {Function<constructor Funktion die mit enchant.Class erstellt wurde>} secondClass Die Klasse aus der das MixingRecipe erstellt wird.
406          * @param [boolean] onlyOwnProperties Wenn dieses Argument true ist, werden Funktionen und Properties der Superklassen der "secondClass" Klasse ignoriert. 
407          * @param [Function] initializeMethod Falls gegeben, wird diese Methode, anstelle der Standard-Initialisierungsmethode, zum Initialisieren der resultierenden Klasse verwendet. 
408          * @returns {Function<constructor Funktion die mit enchant.Class erstellt wurde>} Die Klasse, welche das Ergebnis des Mixens beider Klassen darstellt.
409          [/lang]
410          * @example
411          *      var MapGroup = enchant.Class.mixClasses(Map, Group,true);
412          *      var map = new MapGroup(16, 16);
413          *      var SpriteLabel = enchant.Class.mixClasses(Sprite, Label,true);
414          *      var kumaLabel = new SpriteLabel(32,32,'Kuma');
415          * @static
416          */
417         enchant.Class.mixClasses = function(firstClass, secondClass, useOnlyOwnPropertiesForSecondClass, initializeMethod) {
418             return enchant.Class.mixClassesFromRecipe(firstClass,secondClass,enchant.Class.MixingRecipe.createFromClass(secondClass, useOnlyOwnPropertiesForSecondClass, [], ['initialize'], []),initializeMethod);
419         };
420
421         /**
422          [lang:ja]
423          * 設定されたMixingRecipeを先クラスに実行して、新たなクラスを生成してこのクラスを戻る.
424          * 先クラスが変更されない.<br>{@link enchant.Class.MixingRecipe} を参照してください.
425          * 
426          * @param {Function<constructor enchant.Classで生成された関数>} target MixingRecipeを実行される先クラス.
427          * @param {enchant.Class.MixingRecipe} source 先に新しい機能を追加するMixingRecipe.
428          * @returns {Function<constructor enchant.Classで生成された関数>} sourceという製法とtargetというクラスを混ぜた結果クラス.
429          [/lang]
430          [lang:en]
431          * Applies the defined MixingRecipe to the target class creating a new class definition which is then returned.
432          * The target class is not modified directly.<br>See also: {@link enchant.Class.MixingRecipe}.
433          * 
434          * @param {Function<constructor function created with enchant.Class>} target The class to which the recipe will be applied.
435          * @param {enchant.Class.MixingRecipe} source The MixingRecipe which is used to add new functionality to the target.
436          * @returns {Function<constructor function created with enchant.Class>} The class which is the result of mixing the target class with the source recipe.
437          [/lang]
438          [lang:de]
439          * Wendet das übergebene MixingRecipe auf die Zielklasse an, erstellt eine neue Klassendefinition und liefert diese als Rückgabewert zurück.
440          * Die Zielklasse wird nicht modifiziert.<br>Siehe auch: {@link enchant.Class.MixingRecipe}.
441          * 
442          * @param {Function<constructor Funktion die mit enchant.Class erstellt wurde>} target Die Klasse auf die das MixingRecipe angewendet wird.
443          * @param {enchant.Class.MixingRecipe} source Das MixingRecipe, welches genutzt wird um der Zielklasse neue Funktionalität zu verleihen. 
444          * @returns {Function<constructor Funktion die mit enchant.Class erstellt wurde>} Die Klasse, welche das Ergebnis des Mixens der Zielklasse (target) mit dem Rezept (source) darstellt. 
445          [/lang]
446          * @example
447          *      var recipe = new enchant.Class.MixingRecipe({
448          *         // ... see enchant.Class.MixingRecipe
449          *      },{
450          *          // ... see enchant.Class.MixingRecipe
451          *      },{
452          *          // ... see enchant.Class.MixingRecipe
453          *      });
454          *      var NewClass = applyMixingRecipe(Class1,recipe);
455          * @static
456          */
457         enchant.Class.applyMixingRecipe = function(target, source) {
458             var result = enchant.Class.create(target,{});
459             target = result.prototype;
460             for(var recipeKey in source) {
461                 if(source.hasOwnProperty(recipeKey)) {
462                     var currentSource = source[recipeKey];
463                     if(recipeKey === 'overrideMethods') {
464                         for(var methodKey in currentSource) {
465                             if(currentSource.hasOwnProperty(methodKey)) {
466                                 target[methodKey] = currentSource[methodKey];
467                                 if(target._mixing && target._mixing[methodKey]) {
468                                     target._mixing[methodKey] = voidFunction;
469                                 }
470                             }
471                         }
472                     } else if(recipeKey === 'overrideProperties') {
473                         for(var propertyKey in currentSource) {
474                             if(currentSource.hasOwnProperty(propertyKey)) {
475                                 Object.defineProperty(target,propertyKey,currentSource[propertyKey]);
476                             }
477                         }
478                     } else if(recipeKey === 'decorateMethods') {
479                         if(!target._mixing) {
480                             target._mixing = {};
481                         }
482                         for(var key in currentSource) {
483                             if(currentSource.hasOwnProperty(key)) {
484                                 var targetHolder = target;
485                                 if(!target[key]) {
486                                     while(targetHolder instanceof Object && !targetHolder[key]) {
487                                         targetHolder = Object.getPrototypeOf(targetHolder);
488                                     }
489                                 }
490                                 if(target._mixing[key]) {
491                                     var newFunc = targetHolder[key];
492                                     target._mixing[key] = (multipleMixingCombinationFunctionFactory(target._mixing[key],newFunc,key));
493                                 } else {
494                                     target._mixing[key] = targetHolder[key];
495                                     if(!target._mixing[key]) {
496                                         target._mixing[key] = voidFunction;
497                                     }
498                                 }
499                                 target[key] = currentSource[key];
500                             }
501                         }
502                     }
503                 }
504             }
505             return result;
506         };
507     })();
508 }