Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
R-Proto-Class.js
/**
* 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
*
* See also version w/ class(...) wrapper: https://gist.github.com/1367025
*
* by Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
* 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: function () {},
/**
* 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);
}}
});
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;
}}
});
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;
}}
});
var p4D = Point4D.new(10, 20, 30, 2011);
console.log(p4D);
// Results
// --------- Point ---------
//
// Point.initialize 10 20
// Point.move 10 20
// point: 10 20
//
// --------- Point3D ---------
//
// Point.initialize 10 20
// Point.move 10 20
// Point3D.initialize 10 20 30
// 3D point: 10 20 30
//
// --------- Point4D ---------
//
// Point.initialize 10 20
// Point.move 10 20
// Point3D.initialize 10 20 30
// Point4D.initialize 10 20 30 2011
// 4D is 3D point: 10 20 30 + 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.