-
-
Save m4r00p/1366960 to your computer and use it in GitHub Desktop.
R-Proto-Class.js
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
/** | |
* r-proto-class.js | |
* Ruby's semantics | |
* | |
* Features: | |
* - super calls | |
* - using Object.create for inheritance | |
* - Class.new is a wrapper over Class.allocate and Class.initialize | |
* | |
* by Dmitry Soshnikov <[email protected]> | |
* MIT Style License | |
*/ | |
var Class = { | |
/** | |
*allocate | |
* Creates an instance. Default is | |
* the implementation of native `new' | |
*/ | |
allocate: function () { | |
return Object.create(this); | |
}, | |
/** | |
* new | |
* A wrapper over allocated and initialize | |
*/ | |
new: function () { | |
var instance = this.allocate(); | |
this.initialize.apply(instance, arguments); | |
return instance; | |
}, | |
/** | |
* initialize | |
* Configure a newly created instance | |
*/ | |
initialize: emptyFn, | |
/** | |
* super | |
*/ | |
super: function (method) { | |
var parentName = '__' + method + '_invoke__'; | |
var parentObject = this[parentName]; | |
var proto; | |
if (parentObject) { | |
// deeper levels | |
proto = Object.getPrototypeOf(parentObject.proto); | |
} else { | |
// first level (proto of an instance) -- get the next level | |
proto = Object.getPrototypeOf(Object.getPrototypeOf(this)); | |
} | |
this[parentName] = {proto: proto, level: (parentObject ? parentObject.level++ : 0)}; | |
var result = proto[method].apply(this, [].slice.call(arguments, 1)); | |
this[parentName].level--; | |
if (!this[parentName].level) | |
delete this[parentName]; | |
return result; | |
} | |
}; | |
console.log('--------- Point ---------\n'); | |
// Point class | |
var Point = Object.create(Class, { | |
initialize: {value: function (x, y) { | |
console.log('Point.initialize', x, y); | |
this.move(x, y); | |
}}, | |
move: {value: function (x, y) { | |
console.log('Point.move', x, y); | |
this.x = x; | |
this.y = y; | |
}}, | |
toString: {value: function () { | |
return 'point: '.concat(this.x, ' ', this.y); | |
}}, | |
name: {value: "Point"} | |
}); | |
var p = Point.new(10, 20); | |
console.log(p); // <point 10 20> | |
console.log('\n--------- Point3D ---------\n'); | |
var Point3D = Object.create(Point, { | |
initialize: {value: function (x, y, z) { | |
this.super('initialize', x, y); | |
this.z = z; | |
console.log('Point3D.initialize', x, y, z); | |
}}, | |
move: {value: function (x, y, z) { | |
this.super('move', x, y); | |
this.z = z; | |
}}, | |
toString: {value: function () { | |
return '3D ' + this.super('toString') + ' ' + this.z; | |
}}, | |
name: {value: "Point3D"} | |
}); | |
var p3D = Point3D.new(10, 20, 30); | |
console.log(p3D); | |
console.log('\n--------- Point4D ---------\n'); | |
var Point4D = Object.create(Point3D, { | |
initialize: {value: function (x, y, z, time) { | |
this.super('initialize', x, y, z); | |
this.time = time; | |
console.log('Point4D.initialize', x, y, z, time); | |
}}, | |
move: {value: function (x, y, z, time) { | |
this.super('move', x, y, z); | |
this.time = time; | |
}}, | |
toString: {value: function () { | |
return '4D is ' + this.super('toString') + ' + ' + this.time; | |
}}, | |
name: {value: "Point4D"} | |
}); | |
var p4D = Point4D.new(10, 20, 30, 2011); | |
console.log(p4D); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment