Skip to content

Instantly share code, notes, and snippets.

@hirokidaichi
Created April 30, 2014 09:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hirokidaichi/308c1a701c76e845723c to your computer and use it in GitHub Desktop.
Save hirokidaichi/308c1a701c76e845723c to your computer and use it in GitHub Desktop.
var DISPATCH_TABLE = {};
DISPATCH_TABLE.Person = {
intro: function(_self) {
return "I am just a Person,and my name is " + _self.name;
}
};
TYPE_TABLE = {};
ANCESTOR_TABLE = {};
Array.prototype.first = function(predicate) {
for (var i = 0, l = this.length; i < l; i++) {
if (predicate(this[i]))
return this[i];
}
}
Array.prototype.flatten = function() {
return Array.prototype.concat.apply([], this);
}
function sendMessage(object, message, args) {
var tables = [object._singleton_, ancestors(object._class_).map(function(classOrModule) {
return DISPATCH_TABLE[classOrModule]
})].flatten();
var resolved = tables.first(function(table) {
return !!table[message];
});
var method = resolved[message];
return method(object, args);
}
function defClass(className, dispatchTable) {
DISPATCH_TABLE[className] = dispatchTable;
return _classAncestor(className)
}
function defModule(moduleName, dispatchTable) {
DISPATCH_TABLE[moduleName] = dispatchTable;
}
function extend(className, parentName) {
var ancestor = _classAncestor(className);
if (ancestor) throw ("multi inheritance");
return _classAncestor(className, parentName);
}
function include(className, moduleName) {
var ancestor = _includeAncestor(className);
ancestor.unshift(moduleName);
return ancestor;
}
function prepend(className, moduleName) {
var ancestor = _prependAncestor(className);
ancestor.unshift(moduleName);
return ancestor;
}
function singleton(object, dispatchTable) {
object._singleton_ = dispatchTable;
}
function _nullThenSet(obj, key, defaultValue) {
if (!obj[key]) {
obj[key] = defaultValue
}
return obj[key];
}
function _classAncestor(className, setter) {
var ancestor = _nullThenSet(ANCESTOR_TABLE, className, {});
if (setter) {
ancestor.parent = setter;
}
return ancestor.parent;
}
function _includeAncestor(className, setter) {
var ancestor = _nullThenSet(ANCESTOR_TABLE, className, {});
if (setter) {
ancestor.include = setter;
}
return _nullThenSet(ancestor, "module", []);
}
function _prependAncestor(className, setter) {
var ancestor = _nullThenSet(ANCESTOR_TABLE, className, {});
if (setter) {
ancestor.prepend = setter;
}
return _nullThenSet(ancestor, "prepend", []);
}
function ancestors(className) {
return [
_prependAncestor(className).map(ancestors).flatten(),
className,
_includeAncestor(className).map(ancestors).flatten(),
_classAncestor(className)].flatten().filter(function(e) {
return !!e
});
}
defClass("Parent", {});
defClass("Clazz", {});
defModule("A", {});
defModule("B", {});
defModule("C", {});
defModule("D",{});
extend("Clazz", "Parent");
include("Clazz", "A");
include("Clazz", "B");
include("A","D");
prepend("Clazz", "C");
console.log(ancestors('Clazz'));
/*
Work3-1
// class Child < Parent end
function extend(childName,parentName) {
}
Work3-2
// class Child
// include Module
// end
function include(targetClassName,moduleName){
}
Work3-3
// class Child
// prepend Module
// end
function prepend(targetClassName,moduleName){
}
Work3-4
// class << object
//
// end
function singleton(object,dispatchTable){
}
Work3-5
implement method_missing
sendMessage(me,'no_such_a_method') => NoSuchAMethod
Work3-6
implement double dispatch
DISPATCH_TABLE['ClassA']['ClassB'].collide = function(){}
sendMessage([me,you],'collide')
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment