Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // base class
- function Class() { }
- // base class name
- Class.prototype.className = 'Class';
- // lists all parent classes and outputs JSON with it
- Class.prototype.toString = function() {
- var str = '';
- var next = this.__proto__;
- while(next && next.className) {
- str = next.className + ':' + str;
- next = next.__proto__;
- }
- return str.slice(0, -1) + ' ' + JSON.stringify(this);
- };
- // check if class implements specific interface
- Class.prototype.implements = function(item) {
- var next = this;
- while(next) {
- if (next.classImplementations) {
- for(var i = 0, len = next.classImplementations.length; i < len; i++) {
- if (next.classImplementations[i] == item) {
- return true;
- }
- }
- }
- next = next.__proto__;
- }
- return false;
- };
- // check if class extends another class
- Class.prototype.extends = function(item) {
- return this instanceof item;
- };
- // check typeof class
- Class.prototype.typeof = function(item) {
- return item == Class;
- };
- // implement class extension
- Class.extend = function(options) {
- // name is mandatory
- if (! options['name']) throw new Error('name option should be provided for a Class');
- // check for reserved keys
- var reserved = [
- 'super',
- 'typeof', 'extends', 'implements',
- 'className', 'classImplementations', 'classConstructor'
- ];
- reserved.forEach(function(name) {
- if (options[name]) throw new Error('could not extend class ' + options['name'] + ' - ' + name + ' is reserved key');
- });
- // keep in upper scope variables
- var _super = this.prototype;
- var className = options['name'];
- var classImplementations = options['implement'];
- var classConstructor = options['constructor'];
- // class
- function proto(args) {
- args = args || { };
- var i, len;
- // if first, call own constructor as well
- var first = ! args.__secondary;
- args.__secondary = true;
- // call parent constructor
- _super.constructor.call(this, args);
- // for each implementation of parent
- if (_super.classImplementations) {
- for(i = 0, len = _super.classImplementations.length; i < len; i++) {
- // call its constructor
- _super.classImplementations[i].call(this);
- }
- }
- // if parent has consstructor, call it
- if (_super.classConstructor) {
- _super.classConstructor.call(this, args);
- }
- // if first
- if (first) {
- // check and call implementations
- if (classImplementations) {
- for(i = 0, len = classImplementations.length; i < len; i++) {
- classImplementations[i].call(this, args);
- }
- }
- // call own constructor
- classConstructor.call(this, args);
- }
- }
- // inherit prototype
- proto.prototype = Object.create(this.prototype);
- // implement
- if (options['implement']) {
- options['implement'].forEach(function(item) {
- for(var name in item.prototype) {
- proto.prototype[name] = item.prototype[name];
- }
- });
- }
- // set constructor
- proto.prototype.constructor = proto;
- // a way to call parents method
- proto.prototype.super = function(method, args) {
- if (! (args instanceof Array)) {
- args = [ args ];
- }
- return _super[method].apply(this, args);
- };
- // check for typeof
- proto.prototype.typeof = function(item) {
- return item == proto;
- };
- // rename options
- options['className'] = options['name'];
- options['classConstructor'] = options['constructor'].name != 'Object' ? options['constructor'] : function() { };
- options['classImplementations'] = options['implement'];
- // remove garbage
- delete options['name'];
- delete options['constructor'];
- delete options['implement'];
- // implement own extensions
- for(var name in options) {
- proto.prototype[name] = options[name];
- }
- // allow class to be extended
- proto.extend = Class.extend;
- // return class
- return proto;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement