|
这两天在读kissy的源代码,从一开始我就对它的mix()函数充满了敌意。因为无论从哪个角度来看,那都是一个极其低效的实现。不过深入了解这个框架之后,我对kissy中的新的系统构建的模型产生了兴趣,而这种系统构建的方式,也正是由mix()所带来的。
一、对象系统
我们先了解一下对象系统。在《JavaScript语言精髓与编程实践》中谈到过,面向对象系统有三种对象的继承方式,即原型、类和元类。这三种方式都可以构建大型对象系统。在后续讨论之前,我们在名词概念上做一些强调,所谓“对象系统”,是指由“一组对象构成的系统”,这些对象之间存在或不存在某种联系,但通过一些规则组织起来。所谓“面向对象系统”,是指以上述“对象系统”对基础延伸演化的系统,新系统满足前对象系统的组织规则。
所谓对象系统的三个要素,即继承、封装与多态,即是上述组织规则的要件。孟岩同学从C/C++出发,从另一个侧面谈论对象系统,所持的观点我相当认可,这包括所述的“对象范式的基本观念中不包括继承、封装与多态”——这一观点有其确切的背景与思考方法,值得一谈。
(http://blog.csdn.NET/myan/archive/2010/10/09/5928531.ASPx)
我们在这里要讨论的是“对象系统”,即,对象是如何组织起来的问题。在这个问题上,组织规则之一,就是“继承”。JavaScript中基本的继承模型是原型继承,其特点是“新对象实例的特性,复制自一个原型对象实例”。Qomo以及其它的一些项目,通过语言扩展的方式,在JavaScript上添加了类继承的模型,其特点是“对象构建自类,类是其父类的一个派生”,这里的“派生”与“特性复制”有潜在的关系,即:子类的特性也复制自父类。正是因为“派生”其实是特性复制的一种形式,所以事实上Qomo中的类继承,是通过原型继承来实现的,因为原型继承本质上也就是“特性复制”。
无论是原型继承、类继承还是这里没有进一步讨论的元类继承,继承的最终目的是构建一个“对象系统”,而不是“系统”。这一个小小的措辞上的区别,有着本质上的、深刻的意义,这也是我提及到孟岩的上一篇文章的原因。通常,由“继承”入手理解的“对象系统”其实是静态的,以至于我们面向对象系统开发的最后一步,仍然需要框架来驱动之。例如TApp.Run(),或者类似于new App(),等等。继承所带来的,主要仍然是指对象系统的组织性,而非其运行过程中的动态特性。于是我们通过更多类或其它对象系统,来将一个系统的动态特性静态化,例如将对象之间的交互关系抽取出来,变成控制类。我们做这些事情的目的,仅仅是因为我们约定了对象系统的组织规则,要面向这个对象系统开发,也必然满足(或契合)这一组织规则。组织规则限定了我们构建系统的方式——继承、封装与多态,这在一定程度上说是“对象系统构建”的一个方案,并非“系统构建”的方案。而孟岩在上文中讨论的,也正是“系统构建”的问题。所以孟岩提出两点:
1、程序是由对象组成的;
2、对象之间互相发送消息,协作完成任务。
其第一条,是对象系统的基本特性,是谓系统成员;第二条,是对象系统如何演进为系统的特性,是谓系统通讯。一个系统的约束,既包括其成员(以及成员的组织规则),也包括成员间的通讯。
二、用mix()来构建系统
舍弃“继承”这种方式不谈,系统构建还有其它的什么方法吗?
kissy提供了另外一种可能性,即mix(),混合。在kissy系统的核心部分,为一个系统提出了三个概念:
1、原子(meta),一个系统具有至少一个原子,原子是具有mix()能力的一个对象;
2、宿主(host),一个系统有一个依赖的宿主,表明系统的外部环境,系统只是其宿主环境中的部分内容,可以由特定的名称来区别于其它;
3、种子(seed),一个系统诞生自一个种子,种子描述系统上述的meta和host两个方面的特性。
kissy约定,一个系统诞生自一个种子,该种子通过不停地mix()而成长,变成一个复杂的系统。由种子培育成为系统的整个环境,只需要能够理解mix与host,即可以基于seed来构建任意复杂的系统。
上述的逻辑在kissy.js中,描述得相当简单:
(function(host, S) {
var meta = {
mix: function(r, s, ov, wl) {
...
}
},
// If KISSY is already defined, the existing KISSY object will not
// be overwritten so that defined namespaces are preserved.
seed = (host && host[S]) || {},
// The host of runtime environment. specify by user's seed or <this>,
// compatibled for '<this> is null' in unknown engine.
host = seed.__HOST || (seed.__HOST = host || {});
// shortcut and meta for seed.
S = host[S] = meta.mix(seed, meta, false);
return S;
})(this, 'KISSY');
it知识库:继承与混合,略谈系统的构建方式,转载需保留来源!
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。