2010-11-11 00:12:59 -05:00
|
|
|
# ease.js
|
|
|
|
|
|
|
|
ease.js is (to be) a basic collection of CommonJS modules intended to
|
|
|
|
"ease" the transition into JavaScript from other Object-Oriented languages. It
|
|
|
|
provides an intuitive means of achieving classical inheritance and has planned
|
2011-01-11 18:30:32 -05:00
|
|
|
support traits/mixins.
|
2010-11-15 12:11:11 -05:00
|
|
|
|
|
|
|
Current support includes:
|
|
|
|
|
|
|
|
* Easy class creation
|
|
|
|
* Classical inheritance
|
|
|
|
* Abstract classes and methods
|
2011-01-11 18:30:32 -05:00
|
|
|
* Interfaces
|
2011-03-02 23:48:55 -05:00
|
|
|
* Near-completed visibility support in `visibility/master` branch
|
2010-11-11 00:12:59 -05:00
|
|
|
|
|
|
|
**This project is still under development.**
|
|
|
|
|
|
|
|
## Why ease.js?
|
|
|
|
There are already plenty of other means of achieving each of this project's
|
|
|
|
goals, so what's the point of ease.js? The aim of the project is to provide a
|
|
|
|
lightweight library in a CommonJS format which also addresses ES5 issues and is
|
|
|
|
an all-inclusive solution to OO techniques. It satisfies primarily a personal
|
|
|
|
itch.
|
2010-11-15 12:11:11 -05:00
|
|
|
|
|
|
|
|
|
|
|
## How to Use
|
|
|
|
Please note that, as the project is under active development, the API may change
|
|
|
|
until the first release.
|
|
|
|
|
2011-03-03 20:09:01 -05:00
|
|
|
ease.js uses the [CommonJS](http://commonjs.org) module format. In the
|
2010-11-15 12:11:11 -05:00
|
|
|
examples below, [Node.js](http://nodejs.org) is used.
|
|
|
|
|
|
|
|
### Creating Classes
|
|
|
|
If creating a class from scratch, then the process involves extending the base
|
|
|
|
class. The constructor is provided as the `__construct()` method (influenced by
|
|
|
|
[PHP](http://php.net)).
|
|
|
|
|
|
|
|
var Class = require( 'easejs' ).Class;
|
|
|
|
|
2011-03-03 19:45:03 -05:00
|
|
|
var Foo = Class(
|
2010-11-15 12:11:11 -05:00
|
|
|
{
|
|
|
|
foo: '',
|
|
|
|
|
|
|
|
__construct: function( foo )
|
|
|
|
{
|
|
|
|
this.foo = foo;
|
|
|
|
},
|
|
|
|
|
|
|
|
someMethod: function()
|
|
|
|
{
|
|
|
|
console.log( 'someMethod() called' );
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
### Extending Classes
|
|
|
|
Classes may inherit from one-another. If the supertype was created using
|
|
|
|
`Class.extend()`, a convenience `extend()` method has been added to it. Classes
|
|
|
|
that were not created via `Class.extend()` can still be extended by passing it
|
|
|
|
as the first argument to `Class.extend()`.
|
|
|
|
|
|
|
|
Multiple inheritance is not supported. ease.js is very generous with the options
|
|
|
|
it provides to developers as alternatives, so pick whichever flavor your are
|
|
|
|
most comfortable with: interfaces, traits or mixins. Multiple inheritance will
|
|
|
|
not be added in the future due to its problems which have been addressed by
|
|
|
|
interfaces and traits.
|
|
|
|
|
|
|
|
**Note that interfaces, traits and mixins are not yet available. They are
|
|
|
|
planned features and should be available shortly.**
|
|
|
|
|
|
|
|
var SubFoo = Foo.extend(
|
|
|
|
{
|
|
|
|
anotherMethod: function()
|
|
|
|
{
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// if Foo was not created via Class.extend(), this option may be used (has
|
|
|
|
// the same effect as above, even if Foo was created using Class.extend())
|
|
|
|
var SubFoo = Class.extend( Foo,
|
|
|
|
{
|
|
|
|
anotherMethod: function()
|
|
|
|
{
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
### Abstract Classes
|
|
|
|
Abstract classes require that their subtypes implement certain methods. They
|
|
|
|
cannot be instantiated. Classes are automatically considered to be abstract if
|
|
|
|
they contain one or more abstract methods.
|
|
|
|
|
2010-12-27 22:17:21 -05:00
|
|
|
var Class = require( 'easejs' ).Class;
|
2010-11-15 12:11:11 -05:00
|
|
|
|
2011-03-03 19:45:03 -05:00
|
|
|
var AbstractFoo = Class(
|
2010-11-15 12:11:11 -05:00
|
|
|
{
|
|
|
|
// a function may be provided if you wish the subtypes to implement a
|
|
|
|
// certain number of arguments
|
2010-12-27 22:17:21 -05:00
|
|
|
'abstract fooBar': [ 'arg' ],
|
2010-11-15 12:11:11 -05:00
|
|
|
|
|
|
|
// alternatively, you needn't supply implementation details
|
2010-12-27 22:17:21 -05:00
|
|
|
'abstract fooBar2': [],
|
2010-11-15 12:11:11 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
If the abstract method provides implementation details (as shown by
|
|
|
|
`fooBar()`, subtypes must implement at least that many arguments or an exception
|
|
|
|
will be thrown. This ensures consistency between supertypes and their subtypes.
|
|
|
|
|
|
|
|
Abstract classes can be extended from just as an other class. In order for its
|
|
|
|
subtype to be instantiated, it must provide concrete implementations of each
|
|
|
|
abstract method. If any methods are left as abstract, then the subtype too will
|
|
|
|
be considered abstract.
|
|
|
|
|
|
|
|
// can be instantiated because concrete methods are supplied for both
|
|
|
|
// abstract methods
|
|
|
|
var ConcreteFoo = AbstractFoo.extend(
|
|
|
|
{
|
|
|
|
fooBar: function( arg )
|
|
|
|
{
|
|
|
|
},
|
|
|
|
|
|
|
|
fooBar2: function()
|
|
|
|
{
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// cannot be instantiated because one abstract method remains
|
|
|
|
var StillAbstractFoo = AbstractFoo.extend(
|
|
|
|
{
|
|
|
|
fooBar: function( arg )
|
|
|
|
{
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
You may determine if a class is abstract by calling its `isAbstract()` method.
|
|
|
|
The abstract methods are available as a read-only `abstractMethods` property.
|
|
|
|
|
|
|
|
Foo.isAbstract(); // false
|
|
|
|
SubFoo.isAbstract(); // false
|
|
|
|
AbstractFoo.isAbstract(); // true
|
|
|
|
Concretefoo.isAbstract(); // false
|
|
|
|
StillAbstractFoo.isAbstract(); // true
|
|
|
|
|
|
|
|
|
2011-03-03 19:47:48 -05:00
|
|
|
### Interfaces
|
|
|
|
Interfaces can be declared in a very similar manner to classes. All members of
|
|
|
|
an interface must be declared as abstract.
|
|
|
|
|
|
|
|
var MyType = Interface(
|
|
|
|
{
|
|
|
|
'abstract foo': []
|
|
|
|
});
|
|
|
|
|
|
|
|
To implement an interface, use the `implement()` class method:
|
|
|
|
|
|
|
|
var ConcreteType = Class.implement( MyType ).extend(
|
|
|
|
{
|
|
|
|
foo: function() {}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2010-11-15 12:11:11 -05:00
|
|
|
## Use of Reserved Words
|
|
|
|
Though JavaScript doesn't currently implement classes, interfaces, etc, it does
|
|
|
|
reserve the keywords. In an effort to ensure that ease.js will not clash, the
|
|
|
|
following precautions are taken:
|
|
|
|
|
2011-01-11 18:30:32 -05:00
|
|
|
* `Class` is used with a capital 'C'
|
|
|
|
* `Interface` is used with a capital 'I'
|
2010-12-28 17:44:33 -05:00
|
|
|
* Reserved keywords are quoted when used (e.g. in property strings)
|
2010-11-15 12:11:11 -05:00
|
|
|
|