Module: UWA/Class

UWA/Class

Simple Class Prototype Creation and Inheritance API for JavaScript, by passing the prototype object of your Class as parameter.

Simple Class Heritance Example:

Create a Person class and extend Ninja from Person.

var Person = UWA.Class.extend({
    init: function(isDancing){
         this.dancing = isDancing;
    }
});

var Ninja = Person.extend({
    init: function(){
        this._parent( false );
    }
});

var p = new Person(true);
p.dancing; // => true

var n = new Ninja();
n.dancing; // => false

Prototype properties Class Heritance Example:

Create a Person class and extend Ninja from Person. But share an elements object properties cause it's declared in prototype until one of the instance reassign the elements properties.

var Person = UWA.Class.extend({
    elements: {},
    init: function () {

    },
    addElement: function(name, value) {
        this.elements[name] = value;
    }
 });

var Ninja = Person.extend();

var p = new Person(true);
p.addElement('candy', 1);
p.elements; // => {candy: 1}

var n = new Ninja();
n.elements; // => {candy: 1}

p.addElement('sword', 1);
p.elements; // => {candy: 1, sword: 1}

Index

Methods

<static> Class.extend() → {Function}

Create a new Class that inherits from this class.

Example
var Person = UWA.Class.extend({
     init: function (isDancing) {
         this.dancing = isDancing;
      }
 });

var Hideable = {
    hide: function () {
        console.log('Hidden!'); // bypass
    }
 };

 var Ninja = Person.extend(Hideable, {
    init: function(){
        this._parent( false );
    }
 });

 var p = new Person(true);
 p.dancing; // => true

 var n = new Ninja();
 n.dancing; // => false
 n.hide();
Parameters
Type Description
Object | Class | Function

Definitions to implement. All arguments are mixed with the class prototype in order to extend its methods and attributes.

Returns

The new Class based with prop parameters has prototype

Type
Function

<static> Class.implement() → {Class}

Add definitions (also called mixins) to this class.

The most common usage is to pass Objects to define the class, but in some cases it can be useful to aggregate methods from another UWA class too.

Passing a Function will treat it like a "native class", copying its prototype methods. Note: the constructor will always do a call to _previous before being called (cf Pseudo methods below)

Pseudo methods:

Those methods are bound to a method and does not exist outside. They are helper to call an overriden method with the same name.

  • _parent: call the parent method with the same name as the current one.
  • _previous: call the method previous from the previous definition of this class.

Note: if you call _parent in many methods linked by a _previous call, the parent method can be called multiple times.

Predefined definitions:

Some definitions can be found in the UWA.Class.* namespace (example: UWA.Class.Events, UWA.Class.Options...)

Example
var Animal, Elephant;

// The base class
Animal = Class.extend({
    eat: function () {
        console.log('nom nom nom');
    }
});

// Create a class inheriting from Animal
Elephant = Animal.extend();

// We use the Class.Events mixin (which implements the dispatchEvent method)
Elephant.implement(Class.Events, {
    eat: function () {
        // We override the "eat" method of Animal. Before eating, we
        // have to activate the trunk!
        this.activateTrunk();
         // Then we can eat.
        return this._parent();
    },

    activateTrunk: function () {
        this.trunkActivated = true;
        // Call a method from a mixin
        this.dispatchEvent('onActivateTrunk');
    },

    addEvent: function (name, f) {
        // Override the Class.Events addEvent method to prevent adding
        // undefined events
        if (name !== 'onActivateTrunk') {
             throw new Error('nope');
        }

        // Call the previous addEvent method
        return this._previous(name, f);
    }
});

// All those usages are equivalent:

// Prefer this if you are defining a class in a single file
var A = B.extend(C, D);

// You can use this to define a class, then extend its definition (or
// "monkeypatch" it) in a separate file
var A = B.extend(C);
A.implement(D);

// Implement can also have multiple arguments
var A = B.extend();
A.implement(C, D);

// If you want to separate implementations aspects of a class in one or
// multiple files, you can always call implement multiple times
var A = B.extend();
A.implement(C);
A.implement(D);

// Advanced usage:

// Monkey patch an object:
var object = {
    foo: function () { console.log('foo'); }
};
Class.implement.call(object, {
    foo: function () {
        this._previous();
        console.log('bar');
    }
});
object.foo();
// foo
// bar

// Monkey patch a native class
function MyClass() { }
MyClass.prototype.foo = function () {
    console.log('foo');
};
Class.implement.call(MyClass, {
    foo: function () {
    this._previous();
    console.log('bar');
}
});
new MyClass().foo();
// foo
// bar
Parameters
Type Description
Object | Class | Function

Definitions to implement. All arguments are mixed with the class prototype in order to extend its methods and attributes.

Returns

this class

Type
Class

<static> Class.singleton() → {Object}

Creates a singleton instance, inheriting from 'this' class. This method has exactly the same signature as UWA.Class.extend.

Basically, it:

  • creates a class with UWA.Class.extend
  • builds an instance without initializing it
  • wraps all methods with methods who tries to initialize the instance before calling the original method
  • returns the instance.

While the instance is not initialized, when a method is called, the behavior is determined by the 'uninitializedCalls' attribute of the class:

  • with 'initialize' (the default) it will initialize the instance, then call the original method.
  • with 'ignore', nothing will be done.
  • with 'throw', an exception will be thorwn.

The instance can be initalized with the method 'init'. The arguments are passed to the original constructor.

Initialization consists to removing all method wrappers, then calling the constructor (init).

Example
var Person = UWA.Class.extend({
    init: function (isDancing) {
    this.dancing = isDancing;
    },
    isDancing: function () {
    return this.dancing;
    }
});

var ForEverAloneGuy = Person.singleton({
    init: function () {
        this._parent(false);
    }
});

ForEverAloneGuy.isDancing(); // false;

var ViolentGuy = Person.singleton({
    uninitializedCalls: 'throw'
});

try {
    // throws an exception (ViolentGuy does not like to be disturbed when he is not ready)
    ViolentGuy.isDancing();
} catch (e) {

}

ViolentGuy.init(false);
ViolentGuy.isDancing(); // false

var ShyGuy = Person.singleton({
    uninitializedCalls: 'ignore'
});

ShyGuy.isDancing(); // undefined (ShyGuy doesn't know)

ShyGuy.init(true);
ShyGuy.isDancing(); // true
Parameters
Type Description
Object | Class | Function

definitions to implement.

Returns

A singleton instance of a Class

Type
Object