function createDeclared() {
        var arraySlice = Array.prototype.slice, classCounter = 0, Base, forceNew = new Function();

        var SUPER_REGEXP = /(super)/g;

        function argsToArray(args, slice) {
            slice = slice || 0;
            return arraySlice.call(args, slice);
        }

        function isArray(obj) {
            return Object.prototype.toString.call(obj) === "[object Array]";
        }

        function isObject(obj) {
            var undef;
            return obj !== null && obj !== undef && typeof obj === "object";
        }

        function isHash(obj) {
            var ret = isObject(obj);
            return ret && obj.constructor === Object;
        }

        var isArguments = function _isArguments(object) {
            return Object.prototype.toString.call(object) === '[object Arguments]';
        };

        if (!isArguments(arguments)) {
            isArguments = function _isArguments(obj) {
                return !!(obj && obj.hasOwnProperty("callee"));
            };
        }

        function indexOf(arr, item) {
            if (arr && arr.length) {
                for (var i = 0, l = arr.length; i < l; i++) {
                    if (arr[i] === item) {
                        return i;
                    }
                }
            }
            return -1;
        }

        function merge(target, source, exclude) {
            var name, s;
            for (name in source) {
                if (source.hasOwnProperty(name) && indexOf(exclude, name) === -1) {
                    s = source[name];
                    if (!(name in target) || (target[name] !== s)) {
                        target[name] = s;
                    }
                }
            }
            return target;
        }

        function callSuper(args, a) {
            var meta = this.__meta,
                supers = meta.supers,
                l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;
            if (l > pos) {
                args = !args ? [] : (!isArguments(args) && !isArray(args)) ? [args] : args;
                var name = superMeta.name, f = superMeta.f, m;
                do {
                    m = supers[pos][name];
                    if ("function" === typeof m && (m = m._f || m) !== f) {
                        superMeta.pos = 1 + pos;
                        return m.apply(this, args);
                    }
                } while (l > ++pos);
            }

            return null;
        }

        function getSuper() {
            var meta = this.__meta,
                supers = meta.supers,
                l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;
            if (l > pos) {
                var name = superMeta.name, f = superMeta.f, m;
                do {
                    m = supers[pos][name];
                    if ("function" === typeof m && (m = m._f || m) !== f) {
                        superMeta.pos = 1 + pos;
                        return m.bind(this);
                    }
                } while (l > ++pos);
            }
            return null;
        }

        function getter(name) {
            var getters = this.__getters__;
            if (getters.hasOwnProperty(name)) {
                return getters[name].apply(this);
            } else {
                return this[name];
            }
        }

        function setter(name, val) {
            var setters = this.__setters__;
            if (isHash(name)) {
                for (var i in name) {
                    var prop = name[i];
                    if (setters.hasOwnProperty(i)) {
                        setters[name].call(this, prop);
                    } else {
                        this[i] = prop;
                    }
                }
            } else {
                if (setters.hasOwnProperty(name)) {
                    return setters[name].apply(this, argsToArray(arguments, 1));
                } else {
                    return this[name] = val;
                }
            }
        }


        function defaultFunction() {
            var meta = this.__meta || {},
                supers = meta.supers,
                l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;
            if (l > pos) {
                var name = superMeta.name, f = superMeta.f, m;
                do {
                    m = supers[pos][name];
                    if ("function" === typeof m && (m = m._f || m) !== f) {
                        superMeta.pos = 1 + pos;
                        return m.apply(this, arguments);
                    }
                } while (l > ++pos);
            }
            return null;
        }


        function functionWrapper(f, name) {
            if (f.toString().match(SUPER_REGEXP)) {
                var wrapper = function wrapper() {
                    var ret, meta = this.__meta || {};
                    var orig = meta.superMeta;
                    meta.superMeta = {f: f, pos: 0, name: name};
                    switch (arguments.length) {
                    case 0:
                        ret = f.call(this);
                        break;
                    case 1:
                        ret = f.call(this, arguments[0]);
                        break;
                    case 2:
                        ret = f.call(this, arguments[0], arguments[1]);
                        break;

                    case 3:
                        ret = f.call(this, arguments[0], arguments[1], arguments[2]);
                        break;
                    default:
                        ret = f.apply(this, arguments);
                    }
                    meta.superMeta = orig;
                    return ret;
                };
                wrapper._f = f;
                return wrapper;
            } else {
                f._f = f;
                return f;
            }
        }

        function defineMixinProps(child, proto) {

            var operations = proto.setters || {}, __setters = child.__setters__, __getters = child.__getters__;
            for (var i in operations) {
                if (!__setters.hasOwnProperty(i)) {  //make sure that the setter isnt already there
                    __setters[i] = operations[i];
                }
            }
            operations = proto.getters || {};
            for (i in operations) {
                if (!__getters.hasOwnProperty(i)) {  //make sure that the setter isnt already there
                    __getters[i] = operations[i];
                }
            }
            for (var j in proto) {
                if (j !== "getters" && j !== "setters") {
                    var p = proto[j];
                    if ("function" === typeof p) {
                        if (!child.hasOwnProperty(j)) {
                            child[j] = functionWrapper(defaultFunction, j);
                        }
                    } else {
                        child[j] = p;
                    }
                }
            }
        }

        function mixin() {
            var args = argsToArray(arguments), l = args.length;
            var child = this.prototype;
            var childMeta = child.__meta, thisMeta = this.__meta, bases = child.__meta.bases, staticBases = bases.slice(),
                staticSupers = thisMeta.supers || [], supers = childMeta.supers || [];
            for (var i = 0; i < l; i++) {
                var m = args[i], mProto = m.prototype;
                var protoMeta = mProto.__meta, meta = m.__meta;
                !protoMeta && (protoMeta = (mProto.__meta = {proto: mProto || {}}));
                !meta && (meta = (m.__meta = {proto: m.__proto__ || {}}));
                defineMixinProps(child, protoMeta.proto || {});
                defineMixinProps(this, meta.proto || {});
                //copy the bases for static,

                mixinSupers(m.prototype, supers, bases);
                mixinSupers(m, staticSupers, staticBases);
            }
            return this;
        }

        function mixinSupers(sup, arr, bases) {
            var meta = sup.__meta;
            !meta && (meta = (sup.__meta = {}));
            var unique = sup.__meta.unique;
            !unique && (meta.unique = "declare" + ++classCounter);
            //check it we already have this super mixed into our prototype chain
            //if true then we have already looped their supers!
            if (indexOf(bases, unique) === -1) {
                //add their id to our bases
                bases.push(unique);
                var supers = sup.__meta.supers || [], i = supers.length - 1 || 0;
                while (i >= 0) {
                    mixinSupers(supers[i--], arr, bases);
                }
                arr.unshift(sup);
            }
        }

        function defineProps(child, proto) {
            var operations = proto.setters,
                __setters = child.__setters__,
                __getters = child.__getters__;
            if (operations) {
                for (var i in operations) {
                    __setters[i] = operations[i];
                }
            }
            operations = proto.getters || {};
            if (operations) {
                for (i in operations) {
                    __getters[i] = operations[i];
                }
            }
            for (i in proto) {
                if (i != "getters" && i != "setters") {
                    var f = proto[i];
                    if ("function" === typeof f) {
                        var meta = f.__meta || {};
                        if (!meta.isConstructor) {
                            child[i] = functionWrapper(f, i);
                        } else {
                            child[i] = f;
                        }
                    } else {
                        child[i] = f;
                    }
                }
            }

        }

        function _export(obj, name) {
            if (obj && name) {
                obj[name] = this;
            } else {
                obj.exports = obj = this;
            }
            return this;
        }

        function extend(proto) {
            return declare(this, proto);
        }

        function getNew(ctor) {
            // create object with correct prototype using a do-nothing
            // constructor
            forceNew.prototype = ctor.prototype;
            var t = new forceNew();
            forceNew.prototype = null;	// clean up
            return t;
        }


        function __declare(child, sup, proto) {
            var childProto = {}, supers = [];
            var unique = "declare" + ++classCounter, bases = [], staticBases = [];
            var instanceSupers = [], staticSupers = [];
            var meta = {
                supers: instanceSupers,
                unique: unique,
                bases: bases,
                superMeta: {
                    f: null,
                    pos: 0,
                    name: null
                }
            };
            var childMeta = {
                supers: staticSupers,
                unique: unique,
                bases: staticBases,
                isConstructor: true,
                superMeta: {
                    f: null,
                    pos: 0,
                    name: null
                }
            };

            if (isHash(sup) && !proto) {
                proto = sup;
                sup = Base;
            }

            if ("function" === typeof sup || isArray(sup)) {
                supers = isArray(sup) ? sup : [sup];
                sup = supers.shift();
                child.__meta = childMeta;
                childProto = getNew(sup);
                childProto.__meta = meta;
                childProto.__getters__ = merge({}, childProto.__getters__ || {});
                childProto.__setters__ = merge({}, childProto.__setters__ || {});
                child.__getters__ = merge({}, child.__getters__ || {});
                child.__setters__ = merge({}, child.__setters__ || {});
                mixinSupers(sup.prototype, instanceSupers, bases);
                mixinSupers(sup, staticSupers, staticBases);
            } else {
                child.__meta = childMeta;
                childProto.__meta = meta;
                childProto.__getters__ = childProto.__getters__ || {};
                childProto.__setters__ = childProto.__setters__ || {};
                child.__getters__ = child.__getters__ || {};
                child.__setters__ = child.__setters__ || {};
            }
            child.prototype = childProto;
            if (proto) {
                var instance = meta.proto = proto.instance || {};
                var stat = childMeta.proto = proto.static || {};
                stat.init = stat.init || defaultFunction;
                defineProps(childProto, instance);
                defineProps(child, stat);
                if (!instance.hasOwnProperty("constructor")) {
                    childProto.constructor = instance.constructor = functionWrapper(defaultFunction, "constructor");
                } else {
                    childProto.constructor = functionWrapper(instance.constructor, "constructor");
                }
            } else {
                meta.proto = {};
                childMeta.proto = {};
                child.init = functionWrapper(defaultFunction, "init");
                childProto.constructor = functionWrapper(defaultFunction, "constructor");
            }
            if (supers.length) {
                mixin.apply(child, supers);
            }
            if (sup) {
                //do this so we mixin our super methods directly but do not ov
                merge(child, merge(merge({}, sup), child));
            }
            childProto._super = child._super = callSuper;
            childProto._getSuper = child._getSuper = getSuper;
            childProto._static = child;
        }

        function declare(sup, proto) {
            function declared() {
                switch (arguments.length) {
                case 0:
                    this.constructor.call(this);
                    break;
                case 1:
                    this.constructor.call(this, arguments[0]);
                    break;
                case 2:
                    this.constructor.call(this, arguments[0], arguments[1]);
                    break;
                case 3:
                    this.constructor.call(this, arguments[0], arguments[1], arguments[2]);
                    break;
                default:
                    this.constructor.apply(this, arguments);
                }
            }

            __declare(declared, sup, proto);
            return declared.init() || declared;
        }

        function singleton(sup, proto) {
            var retInstance;

            function declaredSingleton() {
                if (!retInstance) {
                    this.constructor.apply(this, arguments);
                    retInstance = this;
                }
                return retInstance;
            }

            __declare(declaredSingleton, sup, proto);
            return  declaredSingleton.init() || declaredSingleton;
        }

        Base = declare({
            instance: {
                "get": getter,
                "set": setter
            },

            "static": {
                "get": getter,
                "set": setter,
                mixin: mixin,
                extend: extend,
                as: _export
            }
        });

        declare.singleton = singleton;
        return declare;
    }
@projectName declare
@github http://github.com/doug-martin/declare.js
@header

Declare is a library designed to allow writing object oriented code the same way in both the browser and node.js.

##Installation

`npm install declare.js`

Or [download the source](https://raw.github.com/doug-martin/declare.js/master/declare.js) ([minified](https://raw.github.com/doug-martin/declare.js/master/declare-min.js))

###Requirejs

To use with requirejs place the `declare` source in the root scripts directory

```

define(["declare"], function(declare){
     return declare({
         instance : {
             hello : function(){
                 return "world";
             }
         }
     });
});

```


##Usage

declare.js provides

Class methods

* `as(module | object, name)` : exports the object to module or the object with the name
* `mixin(mixin)` : mixes in an object but does not inherit directly from the object. **Note** this does not return a new class but changes the original class.
* `extend(proto)` : extend a class with the given properties. A shortcut to `declare(Super, {})`;

Instance methods

* `_super(arguments)`: calls the super of the current method, you can pass in either the argments object or an array with arguments you want passed to super
* `_getSuper()`: returns a this methods direct super.
* `_static` : use to reference class properties and methods.
* `get(prop)` : gets a property invoking the getter if it exists otherwise it just returns the named property on the object.
* `set(prop, val)` : sets a property invoking the setter if it exists otherwise it just sets the named property on the object.


###Declaring a new Class

Creating a new class with declare is easy!

```

var Mammal = declare({
     //define your instance methods and properties
     instance : {

         //will be called whenever a new instance is created
         constructor: function(options) {
             options = options || {};
             this._super(arguments);
             this._type = options.type || "mammal";
         },

         speak : function() {
             return  "A mammal of type " + this._type + " sounds like";
         },

         //Define your getters
         getters : {

             //can be accessed by using the get method. (mammal.get("type"))
             type : function() {
                 return this._type;
             }
         },

          //Define your setters
         setters : {

               //can be accessed by using the set method. (mammal.set("type", "mammalType"))
             type : function(t) {
                 this._type = t;
             }
         }
     },

     //Define your static methods
     static : {

         //Mammal.soundOff(); //"Im a mammal!!"
         soundOff : function() {
             return "Im a mammal!!";
         }
     }
});


```

You can use Mammal just like you would any other class.

```
Mammal.soundOff("Im a mammal!!");

var myMammal = new Mammal({type : "mymammal"});
myMammal.speak(); // "A mammal of type mymammal sounds like"
myMammal.get("type"); //"mymammal"
myMammal.set("type", "mammal");
myMammal.get("type"); //"mammal"


```

###Extending a class

If you want to just extend a single class use the .extend method.

```

var Wolf = Mammal.extend({

  //define your instance method
  instance: {

       //You can override super constructors just be sure to call `_super`
      constructor: function(options) {
         options = options || {};
         this._super(arguments); //call our super constructor.
         this._sound = "growl";
         this._color = options.color || "grey";
     },

     //override Mammals `speak` method by appending our own data to it.
     speak : function() {
         return this._super(arguments) + " a " + this._sound;
     },

     //add new getters for sound and color
     getters : {

          //new Wolf().get("type")
          //notice color is read only as we did not define a setter
         color : function() {
             return this._color;
         },

         //new Wolf().get("sound")
         sound : function() {
             return this._sound;
         }
     },

     setters : {

         //new Wolf().set("sound", "howl")
         sound : function(s) {
             this._sound = s;
         }
     }

 },

 static : {

     //You can override super static methods also! And you can still use _super
     soundOff : function() {
         //You can even call super in your statics!!!
         //should return "I'm a mammal!! that growls"
         return this._super(arguments) + " that growls";
     }
 }
});

Wolf.soundOff(); //Im a mammal!! that growls

var myWolf = new Wolf();
myWolf instanceof Mammal //true
myWolf instanceof Wolf //true

```

You can also extend a class by using the declare method and just pass in the super class.

```
//Typical hierarchical inheritance
// Mammal->Wolf->Dog
var Dog = declare(Wolf, {
   instance: {
       constructor: function(options) {
           options = options || {};
           this._super(arguments);
           //override Wolfs initialization of sound to woof.
           this._sound = "woof";

       },

       speak : function() {
           //Should return "A mammal of type mammal sounds like a growl thats domesticated"
           return this._super(arguments) + " thats domesticated";
       }
   },

   static : {
       soundOff : function() {
           //should return "I'm a mammal!! that growls but now barks"
           return this._super(arguments) + " but now barks";
       }
   }
});

Dog.soundOff(); //Im a mammal!! that growls but now barks

var myDog = new Dog();
myDog instanceof Mammal //true
myDog instanceof Wolf //true
myDog instanceof Dog //true


//Notice you still get the extend method.

// Mammal->Wolf->Dog->Breed
var Breed = Dog.extend({
   instance: {

       //initialize outside of constructor
       _pitch : "high",

       constructor: function(options) {
           options = options || {};
           this._super(arguments);
           this.breed = options.breed || "lab";
       },

       speak : function() {
           //Should return "A mammal of type mammal sounds like a
           //growl thats domesticated with a high pitch!"
           return this._super(arguments) + " with a " + this._pitch + " pitch!";
       },

       getters : {
           pitch : function() {
               return this._pitch;
           }
       }
   },

   static : {
       soundOff : function() {
           //should return "I'M A MAMMAL!! THAT GROWLS BUT NOW BARKS!"
           return this._super(arguments).toUpperCase() + "!";
       }
   }
});


Breed.soundOff()//"IM A MAMMAL!! THAT GROWLS BUT NOW BARKS!"

var myBreed = new Breed({color : "gold", type : "lab"}),
myBreed instanceof Dog //true
myBreed instanceof Wolf //true
myBreed instanceof Mammal //true
myBreed.speak() //"A mammal of type lab sounds like a woof thats domesticated with a high pitch!"
myBreed.get("type") //"lab"
myBreed.get("color") //"gold"
myBreed.get("sound")" //"woof"
```

###Multiple Inheritance / Mixins

declare also allows the use of multiple super classes.
This is useful if you have generic classes that provide functionality but shouldnt be used on their own.

Lets declare a mixin that allows us to watch for property changes.

```
//Notice that we set up the functions outside of declare because we can reuse them

function _set(prop, val) {
    //get the old value
    var oldVal = this.get(prop);
    //call super to actually set the property
    var ret = this._super(arguments);
    //call our handlers
    this.__callHandlers(prop, oldVal, val);
    return ret;
}

function _callHandlers(prop, oldVal, newVal) {
   //get our handlers for the property
    var handlers = this.__watchers[prop], l;
    //if the handlers exist and their length does not equal 0 then we call loop through them
    if (handlers && (l = handlers.length) !== 0) {
        for (var i = 0; i < l; i++) {
            //call the handler
            handlers[i].call(null, prop, oldVal, newVal);
        }
    }
}


//the watch function
function _watch(prop, handler) {
    if ("function" !== typeof handler) {
        //if its not a function then its an invalid handler
        throw new TypeError("Invalid handler.");
    }
    if (!this.__watchers[prop]) {
        //create the watchers if it doesnt exist
        this.__watchers[prop] = [handler];
    } else {
        //otherwise just add it to the handlers array
        this.__watchers[prop].push(handler);
    }
}

function _unwatch(prop, handler) {
    if ("function" !== typeof handler) {
        throw new TypeError("Invalid handler.");
    }
    var handlers = this.__watchers[prop], index;
    if (handlers && (index = handlers.indexOf(handler)) !== -1) {
       //remove the handler if it is found
        handlers.splice(index, 1);
    }
}

declare({
    instance:{
        constructor:function () {
            this._super(arguments);
            //set up our watchers
            this.__watchers = {};
        },

        //override the default set function so we can watch values
        "set":_set,
        //set up our callhandlers function
        __callHandlers:_callHandlers,
        //add the watch function
        watch:_watch,
        //add the unwatch function
        unwatch:_unwatch
    },

    "static":{

        init:function () {
            this._super(arguments);
            this.__watchers = {};
        },
        //override the default set function so we can watch values
        "set":_set,
        //set our callHandlers function
        __callHandlers:_callHandlers,
        //add the watch
        watch:_watch,
        //add the unwatch function
        unwatch:_unwatch
    }
})

```

Now lets use the mixin

```
var WatchDog = declare([Dog, WatchMixin]);

var watchDog = new WatchDog();
//create our handler
function watch(id, oldVal, newVal) {
    console.log("watchdog's %s was %s, now %s", id, oldVal, newVal);
}

//watch for property changes
watchDog.watch("type", watch);
watchDog.watch("color", watch);
watchDog.watch("sound", watch);

//now set the properties each handler will be called
watchDog.set("type", "newDog");
watchDog.set("color", "newColor");
watchDog.set("sound", "newSound");


//unwatch the property changes
watchDog.unwatch("type", watch);
watchDog.unwatch("color", watch);
watchDog.unwatch("sound", watch);

//no handlers will be called this time
watchDog.set("type", "newDog");
watchDog.set("color", "newColor");
watchDog.set("sound", "newSound");


```

###Accessing static methods and properties witin an instance.

To access static properties on an instance use the `_static` property which is a reference to your constructor.

For example if your in your constructor and you want to have configurable default values.

```
consturctor : function constructor(opts){
    this.opts = opts || {};
    this._type = opts.type || this._static.DEFAULT_TYPE;
}
```



###Creating a new instance of within an instance.

Often times you want to create a new instance of an object within an instance. If your subclassed however you cannot return a new instance of the parent class as it will not be the right sub class. `declare` provides a way around this by setting the `_static` property on each isntance of the class.

Lets add a reproduce method `Mammal`

```
reproduce : function(options){
    return new this._static(options);
}
```

Now in each subclass you can call reproduce and get the proper type.

```
var myDog = new Dog();
var myDogsChild = myDog.reproduce();

myDogsChild instanceof Dog; //true
```

###Using the `as`

`declare` also provides an `as` method which allows you to add your class to an object or if your using node.js you can pass in `module` and the class will be exported as the module.

```
var animals = {};

Mammal.as(animals, "Dog");
Wolf.as(animals, "Wolf");
Dog.as(animals, "Dog");
Breed.as(animals, "Breed");

var myDog = new animals.Dog();

```

Or in node

```
Mammal.as(exports, "Dog");
Wolf.as(exports, "Wolf");
Dog.as(exports, "Dog");
Breed.as(exports, "Breed");

```

To export a class as the `module` in node

```
Mammal.as(module);
```