1
1
2
2
class Space.Object
3
3
4
+ # ============= PUBLIC PROTOTYPE ============== #
5
+
4
6
# Assign given properties to the instance
5
7
constructor : (properties ) ->
6
8
@_invokeConstructionCallbacks .apply (this , arguments )
@@ -14,13 +16,26 @@ class Space.Object
14
16
15
17
toString : -> @constructor .toString ()
16
18
19
+ hasSuperClass : -> @constructor .__super__ ?
20
+
21
+ # Returns either the super class constructor (if no param given) or
22
+ # the prototype property or method with [key]
23
+ superClass : (key ) ->
24
+ sup = @constructor .__super__ .constructor
25
+ if key? then sup .prototype [key] else sup
26
+
27
+ # Returns true if the passed in mixin has been applied to this or a super class
17
28
hasMixin : (mixin ) -> _ .contains (@constructor ._getAppliedMixins (), mixin)
18
29
30
+ # This method needs to stay separate from the constructor so that
31
+ # Space.Error can use it too!
19
32
_invokeConstructionCallbacks : ->
20
33
# Let mixins initialize themselves on construction
21
34
for mixin in @constructor ._getAppliedMixins ()
22
35
mixin .onConstruction ? .apply (this , arguments )
23
36
37
+ # ============= PUBLIC STATIC ============== #
38
+
24
39
# Extends this class and return a child class with inherited prototype
25
40
# and static properties.
26
41
#
@@ -128,8 +143,12 @@ class Space.Object
128
143
initialize.apply(this, arguments);
129
144
}' )(Constructor)
130
145
146
+ # Add subclass to parent class
147
+ Parent ._subClasses .push (Child)
148
+
131
149
# Copy the static properties of this class over to the extended
132
150
Child[key] = this [key] for key of this
151
+ Child ._subClasses = []
133
152
134
153
# Copy over static class properties defined on the extension
135
154
if extension .statics ?
@@ -203,18 +222,43 @@ class Space.Object
203
222
else
204
223
@ _applyMixin (mixins)
205
224
225
+ # Returns true if this class has a super class
226
+ @ hasSuperClass: -> @__super__ ?
227
+
206
228
@ isSubclassOf: (sup ) ->
207
229
isSubclass = this .prototype instanceof sup
208
230
isSameClass = this is sup
209
231
return isSubclass || isSameClass
210
232
233
+ # Returns either the super class constructor (if no param given) or
234
+ # the static property or method with [key]
235
+ @ superClass: (key ) ->
236
+ sup = @__super__ .constructor
237
+ if key? then sup[key] else sup
238
+
239
+ # Returns a flat, uniq array of all sub classes
240
+ @ subClasses: ->
241
+ subs = [].concat (@_subClasses )
242
+ subs = subs .concat (subClass .subClasses ()) for subClass in subs
243
+ return _ .uniq (subs)
244
+
245
+ # Returns true if the passed in mixin has been applied to this or a super class
211
246
@ hasMixin: (mixin ) -> _ .contains (@ _getAppliedMixins (), mixin)
212
247
213
- @ _applyMixin: (mixin ) ->
248
+ # ============= PRIVATE STATIC ============== #
249
+
250
+ @_subClasses : []
214
251
252
+ @ _applyMixin: (mixin ) ->
215
253
# Add the original mixin to the registry so we can ask if a specific
216
254
# mixin has been added to a host class / instance
217
- @ _registerMixin mixin
255
+ # Each class has its own mixins array
256
+ hasMixins = @_appliedMixins ?
257
+ areInherited = hasMixins and @ superClass (' _appliedMixins' ) is @_appliedMixins
258
+ if ! hasMixins or areInherited then @_appliedMixins = []
259
+
260
+ # Keep the mixins array clean from duplicates
261
+ @_appliedMixins .push (mixin) if ! _ .contains (@_appliedMixins , mixin)
218
262
219
263
# Create a clone so that we can remove properties without affecting the global mixin
220
264
mixinCopy = _ .clone mixin
@@ -224,8 +268,11 @@ class Space.Object
224
268
delete mixinCopy .onConstruction
225
269
226
270
# Mixin static properties into the host class
227
- _ .extend (this , mixinCopy .statics ) if mixinCopy .statics ?
228
- delete mixinCopy .statics
271
+ if mixinCopy .statics ?
272
+ statics = mixinCopy .statics
273
+ _ .extend (this , statics)
274
+ _ .extend (sub, statics) for sub in @ subClasses ()
275
+ delete mixinCopy .statics
229
276
230
277
# Give mixins the chance to do static setup when applied to the host class
231
278
mixinCopy .onMixinApplied ? .call this
@@ -234,7 +281,11 @@ class Space.Object
234
281
# Copy over the mixin to the prototype and merge objects
235
282
@ _mergeIntoPrototype @prototype , mixinCopy
236
283
237
- @ _getAppliedMixins: -> @_appliedMixins ? []
284
+ @ _getAppliedMixins: ->
285
+ mixins = []
286
+ mixins = mixins .concat (@ superClass ()._getAppliedMixins ()) if @ hasSuperClass ()
287
+ mixins = mixins .concat (@_appliedMixins ) if @_appliedMixins ?
288
+ return _ .uniq (mixins)
238
289
239
290
@ _mergeIntoPrototype: (prototype , extension ) ->
240
291
# Helper function to check for object literals only
@@ -248,22 +299,4 @@ class Space.Object
248
299
else
249
300
value = _ .clone (value) if isPlainObject (value)
250
301
# Set non-existing props and override existing methods
251
- prototype[key] = value
252
-
253
- @ _registerMixin: (mixin ) ->
254
- # A bit ugly but necessary to check that sub classes don't statically
255
- # inherit mixin arrays from their super classes
256
- if @__super__ ?
257
- superMixins = @__super__ .constructor ._appliedMixins
258
- hasInheritedMixins = @_appliedMixins ? and (superMixins is @_appliedMixins )
259
- else
260
- hasInheritedMixins = false
261
-
262
- if hasInheritedMixins
263
- # Create a shallow copy of the inherited mixins array
264
- @_appliedMixins = @_appliedMixins .slice ()
265
- else
266
- @_appliedMixins ?= []
267
-
268
- # Keep the mixins array clean from duplicates
269
- @_appliedMixins .push (mixin) if ! _ .contains (@_appliedMixins , mixin)
302
+ prototype[key] = value
0 commit comments