NAME

Joose.Manual.Classes - Making your classes use Joose (and subclassing)

USING Joose

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).

ALIASES

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.

VERSION & AUTHORITY

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

ANONYMOUS CLASSES

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 () {
                ...
            }
        }
    })

SUBCLASSING (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.

SUBCLASSING NON-JOOSE CLASSES

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:

AUTHOR

Nickolay Platonov nickolay8@gmail.com

Heavily based on the original content of Moose::Manual, by Dave Rolsky autarch@urth.org

COPYRIGHT AND LICENSE

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.