/** * Hilo * Copyright 2015 alibaba.com * Licensed under the MIT License */ /** * Create Example Class: *
 * var Bird = Hilo.Class.create({
 *     Extends: Animal,
 *     Mixes: EventMixin,
 *     constructor: function(name){
 *         this.name = name;
 *     },
 *     fly: function(){
 *         console.log('I am flying');
 *     },
 *     Statics: {
 *         isBird: function(bird){
 *             return bird instanceof Bird;
 *         }
 *     }
 * });
 *
 * var swallow = new Bird('swallow');
 * swallow.fly();
 * Bird.isBird(swallow);
 * 
* @namespace Class Class is created to aid the developer. * @static * @module hilo/core/Class */ var Class = (function(){ /** * Create a class based on the parameters, properties and methods specified. * @param {Object} properties Properties and methods to create the class. * * @returns {Object} Create classes. */ var create = function(properties){ properties = properties || {}; var clazz = properties.hasOwnProperty('constructor') ? properties.constructor : function(){}; implement.call(clazz, properties); return clazz; }; /** * @private */ var implement = function(properties){ var proto = {}, key, value; for(key in properties){ value = properties[key]; if(classMutators.hasOwnProperty(key)){ classMutators[key].call(this, value); }else{ proto[key] = value; } } mix(this.prototype, proto); }; var classMutators = /** @ignore */{ Extends: function(parent){ var existed = this.prototype, proto = createProto(parent.prototype); //inherit static properites mix(this, parent); //keep existed properties mix(proto, existed); //correct constructor proto.constructor = this; //prototype chaining this.prototype = proto; //shortcut to parent's prototype this.superclass = parent.prototype; }, Mixes: function(items){ items instanceof Array || (items = [items]); var proto = this.prototype, item; while(item = items.shift()){ mix(proto, item.prototype || item); } }, Statics: function(properties){ mix(this, properties); } }; /** * @private */ var createProto = (function(){ if(Object.__proto__){ return function(proto){ return {__proto__: proto}; }; }else{ var Ctor = function(){}; return function(proto){ Ctor.prototype = proto; return new Ctor(); }; } })(); /** * Mixed property or method. * @param {Object} target Mixed audiences. * @param {Object} source The source whose methods and properties are to be mixed. It can support multiple source parameters. * @returns {Object} Mixed audiences. */ var mix = function(target){ for(var i = 1, len = arguments.length; i < len; i++){ var source = arguments[i], defineProps; for(var key in source){ var prop = source[key]; if(prop && typeof prop === 'object'){ if(prop.value !== undefined || typeof prop.get === 'function' || typeof prop.set === 'function'){ defineProps = defineProps || {}; defineProps[key] = prop; continue; } } target[key] = prop; } if(defineProps) defineProperties(target, defineProps); } return target; }; var defineProperty, defineProperties; try{ defineProperty = Object.defineProperty; defineProperties = Object.defineProperties; defineProperty({}, '$', {value:0}); }catch(e){ if('__defineGetter__' in Object){ defineProperty = function(obj, prop, desc){ if('value' in desc) obj[prop] = desc.value; if('get' in desc) obj.__defineGetter__(prop, desc.get); if('set' in desc) obj.__defineSetter__(prop, desc.set); return obj; }; defineProperties = function(obj, props){ for(var prop in props){ if(props.hasOwnProperty(prop)){ defineProperty(obj, prop, props[prop]); } } return obj; }; } } return {create:create, mix:mix}; })();