此模块提供强大的面向对象编程能力,非常感谢mootools等先行者做出的有益探索,虽然现在我放出来的版本比最初的削减了许多功能,但依然非常强大。
/*dom Framework version 1.0 Copyright 2010 Dual licensed under the MIT or GPL Version 2 licenses. author: <ruby> <rb>司徒正美<rp>(zhongqincheng)</rp></rb><rt>しとぅなさみ</rt></ruby> http://www.cnblogs.com/rubylouvre/ */ //========================================= // OOP模块 提供强大的面向对象编程, ruby风格的继承机制 //========================================== ;;;(function(dom,window,undefined){ dom.provide("oop"); var classMethods = (function() { var include = ["constructor"], extend = 'prototype $supers $super extend include'.toArray(); function cleanModule(module, array) { array = array == 'extend' ? extend : include for(var key in module){ if(module.hasOwnProperty(key) && array.contains(key)){ delete module[key] } } return module; } return { //桥梁模式,将实现化与抽象化脱耦,便得两者可以独立地变化 //http://javascript.crockford.com/prototypal.html inherit: function(parent) { if (parent && parent.prototype) { var bridge = function() {}; bridge.prototype = parent.prototype; this.prototype = new bridge; this.$super = parent; } this.$supers = [];//这里的this为类 while (parent) { if(!dom.isPureObject(parent)){//父类不能为默认添加的Object this.$supers.push(parent); parent = parent.$super; } } return this.prototype.constructor = this; }, alias : function(oldName, newName){ var proto = this.prototype; if (dom.isString(oldName)){ var method = proto[oldName] method && (proto[newName] = method); }else if(is(oldName,"Object")){ dom.each(oldName,function(neo,old){ this.alias(old,neo) },this) } return this; }, //为新类添加一些类成员 extend: function() { dom.toArray(arguments).each(function(module){ dom.mixin(this, cleanModule(module, 'extend')); },this); return this; }, //为新类添加原型成员,如果它们是函数,则判断其与父类有没有同名方法, //有则改写当前类的成员,在它上面添加一个$super属性 include: function() { var $supers = this.$supers.pluck('prototype'); dom.slice(arguments).each(function(module){ cleanModule(module, 'include');//去除模块包中那些危险属性 dom.keys(module).each(function(key){ var value = module[key],isFn = dom.is(value,"Function"); if(key.startsWith("protected ")){ key = key.toArray()[1]; if(isFn){ value._protected = true; } } var parent = $supers.first(function(proto) { return dom.is(proto[key],"Function"); }); this.prototype[key] = isFn ? (function( method, key, parent) { return function() { parent && (this.$super = parent[key]); if (method._protected && this._method == null){ throw new Error('The method "' + key + '" is protected!'); } this._method = arguments.callee; var result = method.apply(this, arguments); delete this._method; return result; }; })(value, key, parent) :value; if(isFn){ this.prototype[key].toString = function(){ return String(value); } } },this); },this); return this; } } })(); //第一类工厂 //{inherit :superclass,include:instance_member,extend:class_member,singleton:boolean} dom.oop = function(obj){ obj = obj || {}; //新类的原始构造器 var init = init || obj.init || dom.noop; delete obj.init; //父类 var superclass = obj.inherit || Object; //判定是否需要实现单例 var singleton = !!obj.singleton ; delete obj.singleton; //------------------创建新类-------------------------------------------- var klass = function() { if(singleton && klass.instance){//实现单例模式 return klass.instance } superclass.apply(this, arguments); init.apply(this, arguments); if(singleton) klass.instance = this; return this; }; //添加泛化成员与原型成员 dom.mixin(klass, classMethods).inherit(superclass); ["extend", "include"].each(function(name) { if (obj[name]) { var modules = dom.toArray(obj[name]); klass[name].apply(klass, modules); delete obj[name]; } }); var proto = klass.prototype; klass.include(obj); if(!proto.__proto__){//修复IE与Opera中的第二条原型链 proto.__proto__ = proto } proto.$super = superclass; klass.toString = function(){//重写构造子的toString return init.toString(); } return klass } })(window[escape(document.URL.split("#")[0])],this);
一些示例:
继承。
var Animal = dom.oop({ init: function(name) { this.name = name; }, eat: function() { dom.console.log('yummie'); } }); var Human = dom.oop({ inherit: Animal,//注意这里,使用inherit speak: function() { dom.console.log(this.name + ' said bla bla bla'); } }); var peter = new Human('peter'); peter.eat();//yummie peter.speak();//peter said bla bla bla var Pat = dom.oop({ inherit: Human,//注意这里,使用inherit init: function(name,age) {//注意这里name this.age = age//隐式调用父类构造子 } }); var pat = new Pat('pat',18); dom.console.log(pat.name)//pat dom.console.log(pat.age)//18 pat.speak();//pat said bla bla bla
单例类。
var God = dom.oop({ init:function(name){ this.name = name; this.alertName = function(){ dom.console.log(this.name) } }, singleton:true//注意这里,使用singleton属性 }); var god = new God("耶和华"); god.alertName(); //alerts 耶和华 var lucifer = new God("撒旦"); lucifer.alertName(); //alerts 耶和华 dom.console.log(god === lucifer )//alerts true
内部方法,只能用于类的内部与其子类。注意,是方法不是属性。
var Person = dom.oop({ init: function(name){ this.name = name; }, "protected secret": function(){//定义一个内部方法,要用"protected "作为前缀 return 'I sometimes like girly drinks'; }, describe: function(){ return "Hi, I'm #{name}. #{secret}. I kid, I kid.".instead({ name: this.name, secret: this.secret() }); } }); var scott = new Person('司徒正美'); try{ scott.secret() }catch(e){ dom.console.error(e);//Error: The method "secret" is protected! } dom.console.log(scott.describe());//Hi, I'm Scott. I sometimes like girly drinks. I kid, I kid.
更多见文档!
下载回来后对着文件点右键-->属性-->解除锁定。
如果大家对上述方法有什么更好的实现,请不吝赐救!