Last active
August 29, 2015 14:03
-
-
Save emorikawa/9275c0de23176ae5031a to your computer and use it in GitHub Desktop.
Advanced Coffeescript Mixins
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.include = (obj) -> | |
console.log @ | |
@::[key] = value for key, value of obj; @ | |
Module = {} | |
Module.Foo = (_super) -> | |
overwriteMethod: -> "Foo" | |
extendMethod: -> "Foo" | |
fooMethod: -> @ | |
boundFooMethod: => @ | |
class Baz | |
class Bar extends Baz | |
include: (module, _super) -> | |
for key, value of module.call(@, _super) | |
@[key] = value unless @[key]? | |
return @ | |
constructor: -> | |
@include Module.Foo, Bar.__super__ | |
super | |
overwriteMethod: -> "Bar" | |
extendMethod: -> Module.Foo().extendMethod() + "Bar" | |
barMethod: -> @ | |
boundBarMethod: => @ | |
console.log "---" | |
b = new Bar | |
console.log "b = new Bar --->", b | |
console.log "b.overwriteMethod() --->", b.overwriteMethod() | |
console.log "b.extendMethod() --->", b.extendMethod() | |
console.log "---" | |
console.log "b.barMethod() --->", b.barMethod() | |
console.log "b.boundBarMethod() --->", b.boundBarMethod() | |
console.log "b.fooMethod() --->", b.fooMethod() | |
console.log "b.boundFooMethod() --->", b.boundFooMethod() | |
console.log "---" | |
console.log "b.barMethod.apply(null) --->", b.barMethod.apply(null) | |
console.log "b.boundBarMethod.apply(null) --->", b.boundBarMethod.apply(null) | |
console.log "b.fooMethod.apply(null) --->", b.fooMethod.apply(null) | |
console.log "b.boundFooMethod.apply(null) --->", b.boundFooMethod.apply(null) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_extends = (child, parent) -> | |
for key of parent | |
if {}.hasOwnProperty.call(parent, key) then child[key] = parent[key] | |
child::[key] = parent::[key] for key of parent.prototype | |
child.__super__ = parent.prototype | |
return child | |
class window.Foo | |
overwriteMethod: -> "Foo" | |
extendMethod: -> "Foo" | |
fooMethod: -> @ | |
boundFooMethod: => @ | |
class window.Baz | |
class window.Bar extends Baz | |
@include: (module) -> | |
_extends(@, module) | |
_extends(module, _super) | |
@include Foo | |
overwriteMethod: -> "Bar" | |
extendMethod: -> super + "Bar" | |
barMethod: -> @ | |
boundBarMethod: => @ | |
console.log "---" | |
window.b = new Bar | |
console.log "b = new Bar --->", b | |
console.log "b.overwriteMethod() --->", b.overwriteMethod() | |
console.log "b.extendMethod() --->", b.extendMethod() | |
console.log "---" | |
console.log "b.barMethod() --->", b.barMethod() | |
console.log "b.boundBarMethod() --->", b.boundBarMethod() | |
console.log "b.fooMethod() --->", b.fooMethod() | |
console.log "b.boundFooMethod() --->", b.boundFooMethod() | |
console.log "---" | |
console.log "b.barMethod.apply(null) --->", b.barMethod.apply(null) | |
console.log "b.boundBarMethod.apply(null) --->", b.boundBarMethod.apply(null) | |
console.log "b.fooMethod.apply(null) --->", b.fooMethod.apply(null) | |
console.log "b.boundFooMethod.apply(null) --->", b.boundFooMethod.apply(null) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_ = {} | |
_.isFunction = (obj) -> typeof obj is 'function' | |
_.extend = (obj, args...) -> | |
for source in args | |
obj[prop] = source[prop] for prop of source if source? | |
return obj | |
class window.Foo | |
overwriteMethod: -> "Foo" | |
extendMethod: -> "Foo" | |
fooMethod: -> @ | |
boundFooMethod: => @ | |
class window.Baz | |
bazMethod: -> "Baz" | |
class window.Bar extends Baz | |
@include: (mixin) -> | |
if not mixin | |
return throw 'Supplied mixin was not found' | |
if not _ | |
return throw 'Underscore was not found' | |
mixin = mixin.prototype if _.isFunction(mixin) | |
# Make a copy of the superclass with the same constructor and use it | |
# instead of adding functions directly to the superclass. | |
if @.__super__ | |
tmpSuper = _.extend({}, @.__super__) | |
tmpSuper.constructor = @.__super__.constructor | |
@.__super__ = tmpSuper || {} | |
# Copy function over to prototype and the new intermediate superclass. | |
for methodName, funct of mixin when methodName not in ['included'] | |
@.__super__[methodName] = funct | |
if not @prototype.hasOwnProperty(methodName) | |
@prototype[methodName] = funct | |
mixin.included?.apply(this) | |
this | |
@include Foo | |
overwriteMethod: -> "Bar" | |
extendMethod: -> super + "Bar" | |
barMethod: -> @ | |
boundBarMethod: => @ | |
console.log "---" | |
window.b = new Bar | |
console.log "b = new Bar --->", b | |
console.log "b.overwriteMethod() --->", b.overwriteMethod() | |
console.log "b.extendMethod() --->", b.extendMethod() | |
console.log "---" | |
console.log "b.barMethod() --->", b.barMethod() | |
console.log "b.boundBarMethod() --->", b.boundBarMethod() | |
console.log "b.fooMethod() --->", b.fooMethod() | |
console.log "b.boundFooMethod() --->", b.boundFooMethod() | |
console.log "b.bazMethod() --->", b.bazMethod() | |
console.log "---" | |
console.log "b.barMethod.apply(null) --->", b.barMethod.apply(null) | |
console.log "b.boundBarMethod.apply(null) --->", b.boundBarMethod.apply(null) | |
console.log "b.fooMethod.apply(null) --->", b.fooMethod.apply(null) | |
console.log "b.boundFooMethod.apply(null) --->", b.boundFooMethod.apply(null) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment