blend-class-system
v2.5.23
Published
BlendJS Object Oriented Class System For Node.JS
Downloads
95
Maintainers
Readme
BlendJS Core Class System
About:
BlendJS is a full stack JavaScript Web Application Framework. At the moment It is in development and in it's early stages.
But before BlendJS is ready for use I would like to release it's classical class system to anyone who is interested. I hope you enjoy it and let me know if you happen to find any bugs. Don't forget to give this project a star at npmjs.org :)
IMPORTANT: This repository is created to enable BlendJS's class system within Node.js. It does not provide useful functionality in the browser. For the browser version you need to use the BlendJS Web SDK!
Getting Started:
BlendJS's class system implements and provides the following functionality.
- Define classes using
Blend.defineClass(...)
. - Instantiate objects from previously defined classes using
Blend.create(...)
. - Extend from existing classes to make custom and specialized classes.
- Class overriding, that is changing the current implementation of a class without really extending it.
- Singleton classes, which are classes that have only one instance and are instantiated automatically.
- Multiple inheritance using mixins. You can mix other classes into your own classes to achieve multiple inheritance.
- Function overriding, that is the ability to override a function and be able to call it's parent function.
- Static members. These are functions and properties attached to a class. Great to make utility classes.
- Automatic namespaces. BlendJS groups your classes into their corresponding namespaces without headache.
- Automatic dependency resolving. BlendJS (both Node.js and browser versions) automatically resolves class
dependencies so you don't need to use
require
all the time. - Integration with Node.js
Defining Classes
To define a class in BlendJS we make use of the Blend.defineClass(...)
function, by providing it a FQDN class name and an implementation as a JS object.
For example:
Blend.defineClass('MyCRM.models.Person', {
/**
* @type {string} A person's firstname
*/
firstName: null,
/**
* @type {string} A person's lastname
*/
lastName: null,
/**
* Gets the fullname of a person
* @returns {String}
*/
getFullname: function () {
var me = this;
return me.firstName + ' ' + me.lastName;
}
});
Instantiating Objects
To create or instantiate an object in BlendJS we make use of Blend.create(...)
function, by providing it a class name and optionally an object as configuration to initialize it's
property values. For example:
var person = Blend.create('MyCRM.models.Person', {
firstName: 'Jane',
lastName: 'Eyre'
});
person.getFullname();
Extending Classes
In BlendJS you can create new classes by extending from other classes using the extend
configuration
directive. In the following example we create new class called MyCRM.models.Employee
by extending it
from MyCRM.models.Person
.
Blend.defineClass('MyCRM.models.Employee', {
/**
* Where we extend from the Person class
*/
extend: 'MyCRM.models.Person',
/**
* @type {string} A employee's department
*/
department: null,
/**
* @type {string} A employee's base salary
*/
baseSalary: 1000,
/**
* Let us return from information
*/
getInfo: function () {
var me = this;
return me.getFullname() +
' makes USD' + me.baseSalary +
' and works at ' + me.department;
}
});
var employeeNoOne = Blend.create('MyCRM.models.Employee', {
department: 'Sales',
firstName: 'Johny',
lastName: 'Bravo'
});
employeeNoOne.getInfo();
Blend.BaseClass The Root Of All Classes
BlendJS implicitly extends from Blend.BaseClass
when you do not provide a
parent class like we did in MyCRM.models.Person
. The Blend.BaseClass
encapsulates important functionality when initializing and creating an object.
Blend.defineClass('My.cool.Class', {
// BlendJS extends automatically from Blend.BaseClass if you leave out the
// extend:'...' directive
extend: 'Blend.BaseClass',
doCoolThings: function () {
return;
}
});
The Class Constructor
Every class in BlendJS can have a constructor. The class constructor in BlendJS
is the init(...)
function. You can provide your own constructor when you define
a class. The only requirement is that you need to call the parent constructor to help
BlendJS handle things correctly. For example:
Blend.defineClass('MyCRM.models.Employee', {
extend: 'MyCRM.models.Person',
department: null,
baseSalary: 1000,
/**
* Hey,..We have our own constructor now :)
*/
init: function () {
var me = this;
// Let's call the parent constructor first.
me.callParent.apply(me, arguments);
// Now let's get down to business
if (me.department === 'IT') {
me.baseSalary += 2000;
}
}
});
VERY IMPORTANT: When overriding a class constructor (the init
function)
you always need to call the parent constructor by this.callParent.apply(this,arguments)
,
otherwise the initialization functionality from the Blend.BaseClass
will not be executed
correctly and you end up having a broken object!
Function Overriding
Sometimes you need to implement custom functionality on a existing class function.
This is very easy in BlendJS. You just override the function, by creating a function with the
same name, and if you happen to need to call the parent function, you use the callParent
utility.
In the example below we will make getFullname
to return everything in uppercase:
Blend.defineClass('MyCRM.models.Employee', {
extend: 'MyCRM.models.Person',
/**
* Override from Person
*/
getFullname: function () {
var me = this,
// call the parent getFullname function from the Person class
fullName = me.callParent.apply(me, arguments);
return fullName.toUpperCase();
}
});
Multiple Inheritance Using Mixins
TODO...
Singletons
In BlendJS Singletons are objects that are automatically instantiated and exist
throughout the entire life-cycle of an application. Once you mark a class as
a singleton
, BlendJS creates an object with the same name as the class
itself and initializes that object to be used further. Please note that you
cannot create multiple instances of a singleton class. There can be only one
instance of a singleton:
/**
* Create a singleton
*/
Blend.defineClass('CRM.utils.Mailer', {
// make this class a singleton
singleton: true,
sendMail: function (from, to, subject, message) {
/// Send mail :)
}
});
// Using singletons
Blend.defineClass('Some.Class', {
doWork: function () {
// Here is how we use the singleton
CRM.utils.Mailer.sendMail(
'[email protected]',
'[email protected]',
'message subject',
'message body'
);
}
});
Static Members
Normally class functions are only available when an object is instantiated from a class. In contrast to class function, static functions and properties can directly be accessed from the class itself. Static functions and properties can be best used to provide utility functions or constants without the need for instantiation:
Blend.defineClass('CrmApp.MessageBox', {
/**
* We define static properties like this
*/
statics: {
BUTTON_OK: 1,
BITTON_CANCEL: 2,
BUTTON_YES: 4,
BUTTON_NO: 8,
ICON_INFO: 'b-icon-info',
ICON_WARN: 'b-icon-warn',
ICON_ERROR: 'b-icon-error'
},
/**
* Creates a modal message box
*/
show: function (title, message, icon, button) {
// This is an instanse function
}
});
/**
* Let's create a messagebox
*/
var msgBox = Blend.create('CrmApp.MessageBox');
msgBox.show(
'Order',
'Order creation complete',
CrmApp.MessageBox.ICON_INFO,
CrmApp.MessageBox.BUTTON_OK
);
Class Dependency Resolution
BlendJS includes a built-in class resolution systems that automatically resolves
and imports classes into your program. In Node.js this is done behind the scene.
For the browser version of BlendJS the blend build
utility parses your
classes and compiles a list of every class (with their right order of inclusion)
to be loaded into a HTML page.
Class definition in BlendJS comes with a configuration directive called requires
which is used by the dependency analyzer to import class dependencies. Here is how
it works in Node.js:
Blend.defineClass('Builder.core.Main', {
// These classes will be loaded automatically.
// You don't need to call require(....)
requires: [
'Builder.utils.Resources',
'Builder.utils.CommandLine',
'Blend.mvc.Application'
],
version: '2.0',
run: function () {
//....
//....
}
});
In the example above BlendJS will automatically call the require(...)
method
to load the three dependencies defined in the required
configuration directive.
To help BlendJS you need to put and create your class files in a directory order
identical to the class namespace. For example:
For App.data.Model
we executerequire('/path/to/src/App/data/Model.js')
For Blend.mvc.Application
we execute require('/path/to/Blend/mvc/Application.js')
But that is not all! BlendJS also checks the following configuration directives to resolve dependencies:
/**
* Automatically load:
*
* extend, override, requires, mixins, and controllers
*/
Blend.defineClass('My.cool.Class', {
extend: 'My.cool.BaseClass', // Get loaded automatically
// These classes get loaded automatically
requires: [
'Blend.mvc.Model',
'Blend.ui.Container'
],
// mixins classes get loaded automatically
mixins: {
mvcProvider: 'Blend.mvc.Provider',
mvcConsumer: 'Blend.mvc.Consumer',
xmlProvider: 'My.cool.data.XmlProvider'
},
// These classes also get loaded automatically
controllers: [
'My.cool.mvc.ProfileController',
'My.cool.mvc.BusinessController'
],
/**
* Does something
*/
doSomething: function () {
//....
//....
}
});
One more thing! When running inside Node.js, you can instruct BlendJS to load your classes from a different location than taking the current directory as the root location. This can be doe by:
Blend.loadPath = __dirname + '/path/to/my/classes/';
BlendJS by default sets the value of Blend.loadPath
to the folder of the file
where require('blend-class-system')
was called for the first time!
Integration With Node.js
Node.js provides a very developer friendly ecosystem for developing JavaScript applications. To use BlendJS’ class system in Node.js there is very little work on your part to get everything in motion.
Get blend-class-system installed.
First of all you need to install blend-class-system
. In Node.js you either add blend-class-system
to your dependencies and update your package or you just install using npm install
.
Let’s see how this goes:
Add blend-class-system
to the dependencies of your package file then run npm update
{
"name": "MyApp",
.....
"dependencies": {
"blend-class-system": "*"
}
}
Or just run npm install blend-class-system
if you do not have a package.json
for your project
Next you need to require('blend-class-system');
in the main file of your project. You need to do this only
once. BlendJS will make itself available from the global scope of your Node.js application.
Here is an example from our HelloWorld application:
// make BlendJS available
require('blend-class-system');
// create the main object
var app = Blend.create('Hello.app.Main');
// run this baby
app.run();
Hello World
As a good tradition you can find a fancy Hello World application using the link below: https://github.com/blendsdk/blend-class-system/tree/master/examples/
Additional Functionality:
Class Overriding
Overriding a class basically means the ability to change a class partially or completely for your own needs. Class overriding is a great way to hot-fix a class when you cannot deploy a new version, or when you need to have a function behave differently without extending the class. Class overriding was introduced in BlendJS to make ad-hoc fixes easier. Here is an example:
var brokenEmployee = Blend.create('MyCRM.models.Employee');
brokenEmployee.baseSalary; // should be 1000;
/**
* Now we override the class using the override directive
*/
Blend.defineClass('MyCRM.models.EmployeeHotFix', {
override: 'MyCRM.models.Employee',
baseSalary: 500
});
/**
* Note that we are still using the 'MyCRM.models.Employee' class
*/
var fixedEmployee = Blend.create('MyCRM.models.Employee');
fixedEmployee.baseSalary; // should be 500;
BlendJS treats overridden classes like extended classes in all cases. This means that you can override functions and call their parent function just like when you do extend a class.