define subclass - js
------
define subclass
definition of subclass:
assume there are function A and B, if A.prototype.prototype = B.prototype, then A is subclass of B,
to complete the subclass, there are more things to do than extends prototype, see following steps,
steps to create subclass:
* B.prototype extends from A.prototype
* B.prototype.constructor = B
* in B's constructor body
* use apply()/call() to invoke B's constructor with arguments,
* define new things for B,
* override A's method/property, if necessary,
* define things on new constructor
------
how create a prototype extends from another prototype
how to create sub prototype:
create a new function whose prototype is the super prototype, then the new function could be used as the sub prototype,
how to do:
* in ECMAScript5:
use Object.create(p),
* in ECMAScript3:
create an function, point its prototype to ther super prototype,
util function to create a sub prototype:
/** * create a sub prototype which extends from specified super prototype * * @param: p super prototype * @return sub prototype */ function inherit(p) { if (p == null) throw TypeError(); // p must be a non-null object if (Object.create) // If Object.create() is defined... return Object.create(p); // then just use it. var t = typeof p; // Otherwise do some more type checking if (t !== "object" && t !== "function") throw TypeError(); function f() {}; // Define a dummy constructor function. f.prototype = p; // Set its prototype property to p. return new f(); // Use f() to create an "heir" of p. }
------
abstract class / interface
abstract class & interface:
are class that include abstract method, in js abstract method could be a method that throw an exception,
implementation:
in the subclass, override the abstract method, thus get a class without abstract method,
------
e.g.
include:
* inherit_util.js
include some util methods for inherit,
* subclass_example_1.js
a example use inherit()/extend() directly,
* subclass_example_2.js
a example use defineSubclass(),
* subclass_example_3.js
a example use Function.prototype.extend(),
inherit_util.js:
/** * util function copy enumerable property of p to object o * * @param o * @param p * @returns */ function extend(o, p) { for (prop in p) { // For all props in p. o[prop] = p[prop]; // Add the property to o. } return o; } /** * create a prototype which inherit from specified prototype * * @param p * super prototype * @returns sub prototype */ function inherit(p) { if (p == null) throw TypeError(); // p must be a non-null object if (Object.create) // If Object.create() is defined... return Object.create(p); // then just use it. var t = typeof p; // Otherwise do some more type checking if (t !== "object" && t !== "function") throw TypeError(); // Define a dummy constructor function. function f() { } f.prototype = p; // Set its prototype property to p. return new f(); // Use f() to create an "heir" of p. } /** * util function to define subclass, extends from specified superclass, and add * new methods/properties to prototype/constructor, this function depends on * extend() & inherit(), * * @param superclass * Constructor of the superclass * @param constructor * The constructor for the new subclass * @param methods * Instance methods to copied to prototype, the param should be an * object contain methods/properties * @param statics * Class properties to copied to constructor, the param should be a * object contain methods/properties, * @return the new constructor */ function defineSubclass(superclass, constructor, methods, statics) { // inherit from super prototype constructor.prototype = inherit(superclass.prototype); // set the constructor property of the new prototype constructor.prototype.constructor = constructor; // copy instance properties/methods to copied to prototype if (methods) extend(constructor.prototype, methods); // copy class properties/methods to constructor if (statics) extend(constructor, statics); // Return the class return constructor; } /** * add the extend method to js Function, so that apply to all function of js, * * @param constructor * @param methods * @param statics * @returns the new constructor */ Function.prototype.extend = function(constructor, methods, statics) { return defineSubclass(this, constructor, methods, statics); }; /** * an abstract method, which throws error */ function abstractMethod() { throw new Error("method not implemented"); }
subclass_example_1.js:
// depends on inherit_util.js // super class function A() { this.pone = "A-pone"; this.ptwo = "A-ptwo"; } A.prototype.mone = function() { console.log("A-mone"); }; // super class has a abstract method A.prototype.mtwo = abstractMethod; A.prototype.mthree = function() { console.log("A-mthree"); }; // sub class function B() { // invoke super constructor on sub object, so that to extends things defined // in super constructor, A.apply(this); // override super property from super constructor, this.pone = "B-pone"; } // extends from super prototype B.prototype = inherit(A.prototype); // set the constructor property of sub prototype, after extends prototype, B.prototype.constructor = B; // implemet(override) abstract method of super class B.prototype.mtwo = function() { console.log("B-mtwo"); }; // override method of super class B.prototype.mthree = function() { console.log("B-mthree"); }; function test() { var b = new B(); b.mone(); b.mtwo(); b.mthree(); console.log(b.pone); console.log(b.ptwo); } test();
subclass_example_2.js:
// depends on inherit_util.js // super class function A() { this.pone = "A-pone"; this.ptwo = "A-ptwo"; } A.prototype.mone = function() { console.log("A-mone"); }; // super class has a abstract method A.prototype.mtwo = abstractMethod; A.prototype.mthree = function() { console.log("A-mthree"); }; // sub class function B() { // invoke super constructor on sub object, so that to extends things defined // in super constructor, A.apply(this); // override super property from super constructor, this.pone = "B-pone"; } // extends from super prototype defineSubclass(A, B, { mtwo : function() { console.log("B-mtwo"); }, mfour : function() { console.log("B-mfour"); } }, { sfone : "staticFieldOne" }); function test() { var b = new B(); b.mone(); b.mtwo(); b.mthree(); b.mfour(); console.log(b.pone); console.log(b.ptwo); console.log(b.constructor.sfone); } test();
subclass_example_3.js:
// depends on inherit_util.js // super class function A() { this.pone = "A-pone"; this.ptwo = "A-ptwo"; } A.prototype.mone = function() { console.log("A-mone"); }; // super class has a abstract method A.prototype.mtwo = abstractMethod; A.prototype.mthree = function() { console.log("A-mthree"); }; // sub class function B() { // invoke super constructor on sub object, so that to extends things defined // in super constructor, A.apply(this); // override super property from super constructor, this.pone = "B-pone"; } // extends from super class A.extend(B, { mtwo : function() { console.log("B-mtwo"); }, mfour : function() { console.log("B-mfour"); } }, { sfone : "staticFieldOne" }); function test() { var b = new B(); b.mone(); b.mtwo(); b.mthree(); b.mfour(); console.log(b.pone); console.log(b.ptwo); console.log(b.constructor.sfone); } test();
------