Inherits-Ex
Browser-friendly enhanced inheritance fully compatible with standard node.js
inherits
with dynamic inheritance or creation.
This package modifies and enhances the standard inherits
from node.js
util
module in node environment. It also has a shim for old
browsers with no Object.create
support.
Differs from the standard implementation is:
- coffee-script supports
- static inheritance
- multi-inheritances(inheritance chain) supports
- inherits at anytime.
- you can not declare method/property before inherits in the standard way for it will replace the prototype object.
- duplication inheritance check
- Es6 Class supports
- more helper functions
isInheritedFrom(ctor, superCtor|superCtorName)
Check the ctor whether inherited from superCtormixin(ctor, superCtor|superCtor[])
Mixin the methods and properties of the SuperCtor:
- Clone(Copy) all superCtor's properties(methods) to ctor.
isMixinedFrom(ctor, superCtor|superCtorName)
Whether mixined from superCtorcreateCtor(name, args, body)
Create Ctor(Class) dynamicallycreateObject(ctor, args...)
Create Object instance dynamicallycreateFunction(name, [args,] body[, scope[, values]])
Create Function dynamically
The standard inherits
implementation is in inherits-ex/lib/inheritsDirectly
,
of cause it's the coffee-script supports and browser-friendly.
API
inherits(ctor, superCtor|superCtor[], staticInherit = true)
staticInherit
(boolean): whether static inheritance,defaults to true.
const inherits = require('inherits-ex/lib/inherits')
The enhanced inherits
implementation.
- coffee-script supports
- multi-inheritances(inheritance chain) supports
- inherits at anytime.
- you can not declare method/property before inherits in the standard way for it will replace the prototype object.
- duplication inheritance check
- add the
super_
property(the super ctor) to the ctor. - add the
__super__
property(the super's prototype) to the ctor for the coffeeScirpt super
keyword. - add the
Class
property(point to the current class) to the object's prototype.
- just be care: the ctor may not be the current class.
Known Issues
The default constructor(empty) chain failed for ES6 Class can not call constructor directly if no Reflect.construct(target, args, newTarget)
native supports
const inherits = require('inherits-ex/lib/inherits')
class Root {
constructor() {
this.initialize.apply(this, arguments)
}
initialize() {
console.log('Root.init')
}
}
class A {
initialize() {
const ParentPrototype = this.Class.__super__
ParentPrototype.init.apply(this, arguments)
console.log('A.init')
}
}
inherits(A, Root)
const obj = new A()
usage
# Coffee@1
assert = require('assert')
inherits = require('inherits-ex/lib/inherits')
isInheritedFrom = require('inherits-ex/lib/isInheritedFrom')
log = console.log.bind console
class Root
m: -> log('root')
class A
inherits A, Root
m: ->
log('A')
super
class B
inherits B, Root
m: ->
log('B')
super
class MyClass
# MyClass -> A -> Root
inherits MyClass, B
# MyClass -> A -> B -> Root
inherits MyClass, A
assert.notOk inherits(A, Root) #duplication inheritances prohibited.
assert.ok isInheritedFrom(MyClass, A)
assert.ok isInheritedFrom(MyClass, Root)
assert.ok isInheritedFrom(MyClass, B)
and the following codes do same thing:
class Root
@static: 1
m: -> log('root')
class A
m: ->
log('A')
super
class B
m: ->
log('B')
super
class MyClass
# create inheritances chain:
# MyClass -> A -> B -> Root
inherits MyClass, [A, B, Root]
assert.ok isInheritedFrom(MyClass, A)
assert.ok isInheritedFrom(MyClass, Root)
assert.ok isInheritedFrom(MyClass, B)
assert.equal MyClass.static, 1
inheritsDirectly(ctor, superCtor, staticInherit = true)
staticInherit
(boolean): whether static inheritance,defaults to true.
var inheritsDirectly = require('inherits-ex/lib/inheritsDirectly')
The standard inherits
implementation in node.js environment with coffee-script supports
and browser-friendly.
isInheritedFrom(ctor, superCtor|superCtorName, raiseError=false)
var isInheritedFrom = require('inherits-ex/lib/isInheritedFrom')
return the superCtor's son if ctor is inherited from superCtor.
else return false.
it will use the ctor.name to check whether inherited from superCtorName.
mixin(ctor, superCtor|superCtor[], options:{ filter: number|function})
Mixin the methods and properties of the SuperCtor: Clone(Copy) all superCtor
's properties(methods) to ctor.
- options:
- filter: defaults to 0.
0
: copy all properties(methods)1
: raise error if found a method using super
2
: skip these methods which using super
string[]
: only name in the array of string will be copied.function(name, value){return value}
the callback function of filter.
- name: the property name
- value: the property value.
var mixin = require('inherits-ex/lib/mixin')
mixin all superCtors to ctor.
- duplication mixin or inheritance check
- NOTE::the methods in mixins using
super()
will jump to the old class(not stay on the class). - The mixined properties(methods) are cloned(copied) from superCtors(includes the static members)
- The all mixined properties(methods) are the first parent's ctor(
MixinCtor_
)
- eg,
ctor -> MixinCtor_ -> original parents
## Coffee@2.x
mCallOrder = []
class Root
class C extends Root
m: ->
mCallOrder.push 'C'
super
class A
m: ->
mCallOrder.push 'A'
class A1 extends A
m: ->
mCallOrder.push 'A1'
super
class B
inherits B, Root
class B1 extends B
m: ->
mCallOrder.push 'B1'
super
mixin(B1, [A1, C]).should.be.equal true, 'mixin'
o = new B1()
o.m("a", 12) # call chain: B1::m -> C::m
A::m.should.have.been.calledOnce
A::m.should.have.been.calledWith "a", 12
mCallOrder.should.be.deep.equal ['B1', 'C']
The inheritance chain: B1 -> MixinCtor_ -> B -> Root
All mixins will be added to MixinCtor_
.
isMixinedFrom(ctor, superCtor|superCtorName)
check the ctor whether is mixined from superCtor.
var isMixinedFrom = require('inherits-ex/lib/isMixinedFrom')
createCtor(name, args, body)
Create a constructor(class) dynamically.
name
(string): the class nameargs
(any[]): the optional constructor's args.body
(string): the optional constructor function body.
const createClass = require('inherits-ex/lib/createCtor')
const MyClass = createClass('MyClass', ['a', 'b'], 'this.sum = a + b');
var my = new MyClass(1, 2);
console.log(my.sum);
createObject(ctor, args...)
The helper function to create the object dynamically and arguments provided individually.
var createObject = require('inherits-ex/lib/createObject')
class MyClass {
constructor(a,b) {
this.sum = a + b;
}
}
var o = createObject(MyClass, 1, 2)
console.log(o.sum)
NOTE: It will call the parent constructor if the class is the Empty constructor.
var inherits = require('inherits-ex/lib/inherits')
var createObject = require('inherits-ex/lib/createObject')
class Root {
constructor() {
this.init = 'root'
}
}
class MyClass {
}
inherits(MyClass, Root)
var obj = createObject(MyClass)
assert.equal(obj.init, 'root')
Usage:
class RefObject
constructor: -> @initialize.apply @, arguments
class MyObject
inherits MyObject, RefObject
initialize: (@a,@b)->
super
obj = createObject(MyObject, "a", "b")
# obj = new MyObject("a", "b") # it will have no property a and b.
assert.equal obj.a "a"
assert.equal obj.b "b"
createObjectWith(ctor, [args...])
The helper function to create the object dynamically. provides the arguments as an array (or an array-like object).
var createObjectWith = require('inherits-ex/lib/createObjectWith')
var obj = createObjectWith(MyObject, ['a', 'b'])
NOTE: It will call the parent constructor if the class is the Empty constructor.
createFunction(name, [args,] body[, scope[, values]])
- arguments:
name
(String): the function nameargs
(Array): the function argument list. it's optional.body
(String): the function body.- ``scope` (Object|Array): the optional function scope.
- ignore the
values
if it's an object. - the
value
is required if it's an array. It's the key's name list
value
(Array): the optional function scope's value list. only for the scope
is the Array.
The helper function to create the function dynamically.
var createFunction = require('inherits-ex/lib/createFunction')
Usage:
class RefObject
constructor: -> @initialize.apply @, arguments
class MyObject
inherits MyObject, RefObject
initialize: (@a,@b)->
super
obj = createObject(MyObject, "a", "b")
#obj = new MyObject("a", "b") # it will have no property a and b.
assert.equal obj.a "a"
assert.equal obj.b "b"