npm.io
1.0.2 • Published 9 years ago

sota-class

Licence
MIT
Version
1.0.2
Deps
0
Vulns
0
Weekly
0

Sota-Class.js

This is package for javascript developers that cannot forget OOP.
In Node.js, we have util.inherits to do the inheritance stuffs, but it's not available in browser environment and also discouraged now.
New ES6 with language-level inheritance support is still not popular enough, and we have to use old syntax in many cases.
Then let's try Sota-Class. This module will bring you the familar OOP features with Java language. It's written in pure javscript, no dependency, works well on Node.js/browsers or any javascript environment.

Installation

Node.js

  npm install sota-class
Browser

The easiest way to use the library is with webpack or browserify

Usage

Make sub-class by Class.extends(properties)

Let's create the first class

var assert = require('assert');
var Class = require('sota-class').Class;
var Animal = Class.extends({
  classname: 'Animal',

  // The properties start with '

And here's how to extends a existed class

var Cat = Animal.extends({
  classname: 'Cat',

  $HABITAT: 'kitchen',

  helloWorld: function() {
    return 'Meow';
  },
});

var cat = new Cat('Kitty');

// `initialize` and `getName` methods are inherited from Animal class
assert.equal(cat.getName(), 'Kitty');

// `helloWorld` is overrided
assert.equal(cat.helloWorld(), 'Meow');

// Defined property is overrided as well
assert.equal(Cat.HABITAT, 'kitchen');

How to call the super method

var Lion = Cat.extends({
  classname: 'Lion',

  // If the first parameter of a method is `$super`
  // It's the reference to the ancestor method
  getName: function($super) {
    return $super() + '-Lion';
  },
});

var lion = new Lion('Simba');
// Yeah, the name has the '-Lion' suffix
assert.equal(lion.getName(), 'Simba-Lion');

By default, the ancestor of methods initialize and destroy are called in their subclass' methods automatically, even if you don't do it explicitly

var Duck = Animal.extends({
  classname: 'Duck',

  initialize: function(name) {
    // Do nothing, don't call the ancestor explicitly
  },

  destroy: function() {
    // Also do nothing
  },
});

var duck = new Duck('Donald');
// The name is still set, because Animal's initialize was called automatically
assert.equal(duck.getName(), 'Donald');

// And after the destroy, the name is deleted
duck.destroy();
assert.equal(duck.getName(), undefined);

If you don't want initialize or destroy are called automatically, put the $super as the first method's argument and don't invoke it

var Weirdo = Animal.extends({
  initialize: function($super, name) {
    // I don't want a name
  },
});

var weirdo = new Weirdo('Awesome name');
// Since the initialize was not called, the weirdo's name was not set as well
assert.equal(weirdo.getName(), undefined);
Make the singleton by Class.singleton(properties)

The argument is similar with extends method. But the result is an object instead of Class

var Tom = Cat.singleton({
  // initialize method will be called automatically in hidden scope

  initialize: function($super) {
    // Of course, Tom is an unique creature
    // and doesn't need to pass his name from outside
    $super('Tom');
  },

  confess: function() {
    return 'ILoveJerry';
  },

});

assert.equal(Tom.getName(), 'Tom');
assert.equal(Tom.confess(), 'ILoveJerry');
Make multi-inheritance by Class.implements(interfaces)

It's implemented, but documentation is still in proces...

// TODO
are the static/class property
$HABITAT: 'various', // The others will become the private properties of class instance age: 0, initialize: function(name) { this._name = name; }, getName: function() { return this._name; }, helloWorld: function() { throw new Error('Implement me in derived class'); }, destroy: function() { delete this._name; }, }); var foo = new Animal('Foo'); // Classname is defined in properties assert.equal(Animal.classname, 'Animal'); // Class instance has the same classname value assert.equal(foo.classname, 'Animal'); // Both class and class instance contain the static properties assert.equal(Animal.HABITAT, 'various'); assert.equal(foo.HABITAT, 'various'); // Only the class instance has non-static properties assert.equal(Animal.age, undefined); assert.equal(foo.age, 0); // Initialize method acts the constructor role // and it's called automatically, then the name is set assert.equal(foo.getName(), 'Foo');

And here's how to extends a existed class

__CODE_BLOCK_2__

How to call the __INLINE_CODE_2__ method

__CODE_BLOCK_3__

By default, the ancestor of methods __INLINE_CODE_3__ and __INLINE_CODE_4__ are called in their subclass' methods automatically, even if you don't do it explicitly

__CODE_BLOCK_4__

If you don't want __INLINE_CODE_5__ or __INLINE_CODE_6__ are called automatically, put the __INLINE_CODE_7__ as the first method's argument and don't invoke it

__CODE_BLOCK_5__
Make the singleton by __INLINE_CODE_8__

The argument is similar with __INLINE_CODE_9__ method. But the result is an object instead of Class

__CODE_BLOCK_6__
Make multi-inheritance by __INLINE_CODE_10__

It's implemented, but documentation is still in proces...

__CODE_BLOCK_7__

Keywords