Joose.Manual.Classes - Making your classes use Joose (and subclassing)
Using Joose is very simple, just include the appropriate files in your page (see the Joose.Manual.Installation section) a type:
Class('Person', {
})
That's it, you've made a class with Joose!
There's actually a lot going on here under the hood, so let's step through it.
When you constructing a class with Joose, a properties of 2nd argument passed to Class
call are called builders. These include things like has
, isa
, does
and more.
These builders are what you use to define your class. For example, you might define an attribute and a method:
Class('Person', {
has : {
firstName : { is : 'rw' }
},
methods : {
trimLeading : function () {
...
}
}
})
Attributes are described in the Joose.Manual.Attributes documentation.
When you use Joose, your class will become a subclass of Joose.Meta.Object
. The Joose.Meta.Object
class provides a default constructor and a number of additional methods.
You can read more about this in the Joose document.
Joose creates an instance of Joose.Meta.Class
for your class. This metaclass instance is now available as a meta
property on your class, for example: Person.meta
The metaclass object provides an introspection API for your class. It is also used by Joose itself under the hood to add attributes, compose roles, and so on. In fact, all of Joose's sugar does the real work by calling methods on this metaclass object (and other meta API objects).
In case your global scope already contains Class
symbol, you can use the Joose.Class
alias to declare your classes.
There are also corresponding Joose.Role
and Joose.Module
aliases.
Each class supports the VERSION
and AUTHORITY
builders:
Class('Person', {
VERSION : 0.01,
AUTHORITY : 'jsan:SomeCleverGuy',
...
})
Version is self-explanatory, and "authority" is an URI identifying the author (or another authorizing authority). This information is availbale in corresponding properties
of meta
instance:
Person.meta.VERSION
Person.meta.AUTHORITY
Among other use-cases, this information is used by the dependencies loader JooseX.Namespace.Depended
, which is provided in separate distribution, see JooseX
If you'll omit the class name, Joose will create an anonymous class. Anonymous class behave very much the same as usual class, expect that it will not have publically available constructor's. Its a good idea to capture this constructor in the variable:
var anonoymous = Class({
has : {
firstName : { is : 'rw' }
},
methods : {
trimLeading : function () {
...
}
}
})
isa
builder)Joose provides a simple builder for declaring your parent class: isa
Class('User', {
isa : Person,
has : {
userName : { is : 'rw' }
},
methods : {
trimLeading : function () {
this.SUPER()
...
}
}
})
A class inherit all the attributes and methods from its parent class, and can also re-declare (override) them. In the re-declared method you can use this.SUPER(arg1, arg2, ...)
call to execute the same method from the parent class.
There is also another form of this call : this.SUPERARG(arg)
In this form, arguments are passed in the array, this is the equivalent of this.SUPER.apply(this, arg)
Note that Joose allows a single parent class only. As cleaner alternative to multiple inheritance approach, Joose provides Roles mechanism. See Joose.Manual.Roles.
You can subclass non-Joose classes as well:
require('joose')
var EventEmitter = require('events').EventEmitter
var puts = require('sys').puts
Class('My.Class', {
meta : Joose.Meta.Class,
isa : EventEmitter,
before : {
emit : function (event) {
puts('Emitting event [' + event + ']')
}
}
})
var obj = new My.Class()
obj.emit('yo') // Emitting event [yo]
puts(EventEmitter.meta.hasMethod('emit')) // true
Things to note:
Joose will alter the superclass - it will create a meta
property in it's prototype and constructor.
Actually it will turn the superclass into Joose class, just with meta
of the lower level.
Always specify the desired meta-class (Joose.Meta.Class usually).
Reflection will also work with properties inherited from non-Joose classes. Every function
in the prototype
of such class will be considered as a "method" (unless it has a meta
attached). Everything else will be considered as
"attribute".
Nickolay Platonov nickolay8@gmail.com
Heavily based on the original content of Moose::Manual, by Dave Rolsky autarch@urth.org
Copyright (c) 2008-2011, Malte Ubl, Nickolay Platonov
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.