/*********************************************
* Object Oriented Programming in Javascript *
* *
* N (Package) *
* | *
* +- A (Abstract class) *
* | *
* +- B (Class extends A) *
* | *
* +- I (Interface) *
* | *
* +- C (Class implements I) *
* | *
* +- D (Class extends B implements I) *
* | *
* +- J (Interface) *
* | *
* +- K (Interface extends I, J) *
* | *
* +- L (Interface) *
* | *
* +- E (Class implements K, L) *
* | *
* +- F (Final class) *
* | *
* +- M (Module) *
* *
*********************************************/
// Namespace N
var N = N || {};
// Abstract class A
N.A = function () {
if (notExtending) throw Error("Abstract class");
var self = this;
/***********************************/
// Private members
var __privAtt;
var __privMethod = function () {};
// Public members
self.pubAtt = null;
self.pubMethod = function () { throw Error("Abstract method") };
/***********************************/
// No constructor A
};
// Class B extends A
N.B = function () {
var self = this;
// Extending A, avoiding private static variables
var super = new N.A();
for (var m in super) self[m] = super[m];
/***********************************/
//...
self.B = function () {}; // Constructor
self.pubMethod = function () {
//...
super.pubMethod(); // pubMethod parent class
//...
};
//...
/***********************************/
// Executes constructor B
if (notExtending) self.B.apply(self, arguments);
}
// Prototype chain B -> A
function I () {};
I.prototype = N.A.prototype;
N.B.prototype = new I();
N.B.prototype.constructor = N.B;
// Interface I
N.I = {
//...
CONST: null,
pubMethod: function () { throw Error("Abstract method") }
//...
}
// Class C implements I
N.C = function () {
var self = this;
for (var m in N.I) self[m] = N.I[m]; // Implementing I
/***********************************/
//...
self.C = function () {}; // Constructor
self.pubMethod = function () {}
//...
/***********************************/
if (notExtending) self.C.apply(self, arguments);
}
// Class D extends B implements I
N.D = function () {
var self = this;
for (var m in N.I) self[m] = N.I[m]; // Implementing I
var super = new N.B(); // Extending B
for (var m in super) self[m] = super[m];
/***********************************/
//...
self.D = function () { // Constructor
//...
super.B(); // Constructor parent class
//...
};
self.pubMethod = function () {};
//...
/***********************************/
if (notExtending) self.D.apply(self, arguments);
}
// Prototype chain D -> B -> A
I.prototype = N.B.prototype;
N.D.prototype = new I();
N.D.prototype.constructor = N.D;
// Interface J
N.J = {
//...
CONST2: null,
pubMethod2: function () { throw Error("Abstract method") }
//...
}
// Interface K extends I, J
N.K = {
//...
CONST3: null,
pubMethod3: function () { throw Error("Abstract method") }
//...
}
for (var m in N.I) N.K[m] = N.I[m]; // Extending I
for (var m in N.J) N.K[m] = N.J[m]; // Extending J
// Interface L
N.L = {
//...
CONST4: null,
pubMethod4: function () { throw Error("Abstract method") }
//...
}
// Class E implements K, L
N.E = function () {
var self = this;
for (var m in N.K) self[m] = N.K[m]; // Implementing K
for (var m in N.L) self[m] = N.L[m]; // Implementing L
/***********************************/
//...
self.E = function () {}; // Constructor
self.pubMethod = function () {};
self.pubMethod2 = function () {};
self.pubMethod3 = function () {};
self.pubMethod4 = function () {};
//...
/***********************************/
if (notExtending) self.E.apply(self, arguments);
}
// Final class F
N.F = function () {
if (Extending) throw Error("Final class");
var self = this;
/***********************************/
//...
/***********************************/
self.F.apply(self, arguments);
};
/*********************************************
* Note1: "notExtending" or "Extending" is *
* any mechanism that can tell us that the *
* class is being extended, no big deal ;-) *
* *
* Note2: we can always use helper functions *
* to extend, implement, maintain prototype *
* chain and execute constructor, reducing *
* considerably the extra code *
********************************************/
// Module M
N.M = (function () {
var self = {};
/***********************************/
// Private members
var __privVar;
var __privFunc = function () {
//...
self.pubFunc();
//...
};
// Public members
self.pubVar = null;
self.pubFunc = function () {
//...
__privFunc();
//...
};
/***********************************/
return self;
})();