QoBean技术文档(1):QoBean的基础技术
2007-12-31 16:12 乱世文章 阅读(272) 评论(0) 编辑 收藏 举报//------------------------------------------------------------------------
// QoBean - Qomo's beans
//
// documents group(chs) - Aimingoo, Zhe
//------------------------------------------------------------------------
一、QoBean的发起
---------------------
我对Qomo的不满由来以久,最根深蒂固的便是它的命名空间的实现方式:隐式地维护路径与
命名空间系统。所以有一段时间,我几乎不敢看Qomo的Framework/Names/下的代码。
我对Qomo不满之处很多,但归结起来只有一条:太大太复杂。但它比那些“看起来不怎么复
杂”的项目有太多特性要实现,因此复杂是必然的。我只是一直以来无法跳开一个圈子:为
什么复杂的,一定不能简洁?
QoBean的触动来自于一篇文档(忘掉了出处),说在JavaScript中实现类继承只需要几行代
码而已。我当时想:是啊,只需要几行代码就行了,为什么Qomo的Object.js写了20k代码,
以及包括8个子文件呢?
我决定扔掉所有在Qomo Object Framework中的所有其它的(并不见得是多余的)特性,我想
知道,在Qomo的设计思想中,一个最小化的“类继承”到底需要多少代码?
于是我建立了一个目录QomoMini,现在它被签入到了Qomo的项目中,改名作QoBean。QoBean
是这个子项目的代码名。
二、最初的QoBean
---------------------
当然,首先是从Qomo中的Object.js下手,最初的代码被精减成这样:
=======
function Class(Parent, Name) {
function _Create() {
if (this.Create) this.Create.apply(this, arguments);
}
var Constructor = (Name instanceof Function) ? Name : eval(Name);
var cls = new Function();
if (Parent) Constructor.prototype = Parent.Create.prototype;
_Create.prototype = new Constructor();
_Create.prototype.constructor = _Create;
(Name instanceof Function) || eval(Name + '= _Create');
return cls;
}
TObject = Class(null, Object);
=======
这个代码实现了几项关键功能,包括:
- 支持类声明与类注册
- 支持匿名类
使用示例1, 例如:
=======
// 1. 类声明
function MyObject() {
// 类构造周期
// ...
this.Create = function() {
// 实例构造周期
}
}
// 2. 类注册
TMyObject = Class(TObject, 'MyObject');
// 3. 创建对象
obj = new MyObject();
=======
可见,该例仍然保持了Qomo的一般性语法。
使用示例2, 例如:
=======
arr = [];
arr.push(Class(TObject, function() { //<--注册一个匿名函数为匿名类
// 类声明...
}));
// 创建对象
obj = new arr[0];
=======
该例简单的注册了一个匿名类。匿名类是类厂等设计模式中的基础技术。
三、QoBean alpha 1
---------------------
上述的Class()丢掉了几项Qomo的特性,例如“obj = aClass.Create()”语法,以及没有显
式维护的类继承关系等等。但由于代码基本都是从Qomo的Object.js中截取出来的,因此保留
了Qomo的原始状态。
接下来我们讨论如何在上述基础上实现更多的QoBean特性。
1. _Create()不需要实现为嵌套函数
---------
上面代码中的_Create()被实现为Class()的内嵌函数,因此在执行中它处于一个闭包链的末
端,这会使它的效率稍为低一点。但显然,由于_Create()没有什么地方要引用Class()内的变
量,所以它可以实现在全局——但是如果直接实现在全局又会占用一个标识符。
处理的办法是使用new Function()。
2. eval(Name)的特性
---------
上面代码中试图识别参数Name是否是一个函数,如果是函数则认为是注册匿名类——不需要
重写原标识符,也不需要类名;而eval(Name)用于得到Name所指定的构造器。这一行代码写作:
=======
var Constructor = (Name instanceof Function) ? Name : eval(Name);
=======
然而事实上不需要这么麻烦,eval()函数执行时如果参数不是字符串就会返回该参数本身,
所以更加简洁的代码是:
=======
var Constructor = eval(Name);
=======
3. constructor赋值操作过于啰嗦
---------
无论如何,用两行代码来完成原型重写和constructor赋值是过于啰嗦的,我们有更好的方法。
4. 包括上述特性与修改的新版本
---------
通过下面的修改,可以有更为精简的代码、更高的效率,以及一个外部维护的类名。
=======
// class register util
function Class(Parent, Name) {
var Constructor = eval(Name);
var cls = new Function('Base', 'return new Base');
var _Create = new Funcction('if (this.Create) this.Create.apply(this, arguments)');
Parent && (Constructor.prototype = Parent.Create.prototype);
cls.Create = (_Create.prototype = cls(Constructor)).constructor = _Create;
(Name instanceof Function ? Name = 'Anonymous' : eval(Name + '= cls.Create'),
cls.ClassName = 'T' + Name);
return cls;
}
};
TObject = Class(null, Object);
=======
四、发布QoBean alpha 1的最后修改
---------------------
正式发布的QoBean alpha 1比上面的代码要复杂一些。但复杂的这一部分,就是“框架”与一
个普通的工具函数之间的不同。
我们既然希望QoBean是将来的Qomo V3的基础,那么必然的,我们需要解释将来的Qomo V3是怎
样的一种结构——我们需得先画好蓝图,然后再行建设。
QoBean试图在Qomo V3中添加“元系统”,用于添加新的语言特性/特性集,或者构建新的语言。
通过元系统在QoBean中创建Qomo对象模型的基本框架为:
=======
aClass = new MetaClass();
aClass.Create = new MetaObject();
aObject = new aConstructor_RegedByClass; // or
aObject = aClass.Create();
=======
而在Object.js中,MetaClass与MetaObject的实现非常简单:
=======
MetaClass = Function;
MetaObject = Function;
=======
到了更将来的版本(事实上这个版本已经在开发中),我们会重写这两个“元(数据类型)”,
并由此构建更为复杂的语言逻辑。
此外,为了实现Qomo中的“aClass.Create()”语法,QoBean添加了一些代码,并加入了一个
可选开关,大概的框架代码如下:
=======
Class = function(ext) {
var idx = 0;
var code = ext ? '/
if (this instanceof Function) {/
var i, v=arguments, n=v.length, s="new this.Create(";/
if (n>0) for (i=1,s+="v[0]"; i<n; i++) s += ", v[" + i +"]";/
return eval(s+");");/
}' : '';
code += 'if (this.Create) this.Create.apply(this, arguments)';
return function(Parent, Name) {
var Constructor = eval(Name);
var cls = new MetaClass('Base', 'return new Base');
var _Create = new MetaObject(code);
...
}
}(true); // is delphi extand syntax.
=======
注意上述代码中,变量code的字符串使用了特殊的语法来声明直接量:行末使用“/”,表
明字符串是连续的。
其它代码请参见QoBean的下载包或SVN:
http://blog.csdn.net/aimingoo/archive/2007/12/31/2006369.aspx
五、其它
---------------------
1. QoBean的Namespace.js中添加了命名空间的支持并重写了Class()以支持它;
2. QoBean的代码包包含更多的示例。
3. 所谓“类继承系统”是指继承关系的维护,不包括Qomo中的get/set,以及inherited等特性。