继承与混合,略谈系统的构建方式

http://blog.csdn.net/aimingoo/article/details/6062997

这两天在读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(),等等。继承所带来的,主要仍然是指对象系统的组织性,而非其运行过程中的动态特性。于是我们通过更多类或其它对象系统,来将一个系统的动态特性静态化,例如将对象之间的交互关系抽取出来,变成控制类。我们做这些事情的目的,仅仅是因为我们约定了对象系统的组织规则,要面向这个对象系统开发,也必然满足(或契合)这一组织规则。组织规则限定了我们构建系统的方式——继承、封装与多态,这在一定程度上说是“对象系统构建”的一个方案,并非“系统构建”的方案。而孟岩在上文中讨论的,也正是“系统构建”的问题。所以孟岩提出两点:

•程序是由对象组成的; 
•对象之间互相发送消息,协作完成任务。

其第一条,是对象系统的基本特性,是谓系统成员;第二条,是对象系统如何演进为系统的特性,是谓系统通讯。一个系统的约束,既包括其成员(以及成员的组织规则),也包括成员间的通讯。

 

二、用mix()来构建系统

 

舍弃“继承”这种方式不谈,系统构建还有其它的什么方法吗?

kissy提供了另外一种可能性,即mix(),混合。在kissy系统的核心部分,为一个系统提出了三个概念:

1、原子(meta),一个系统具有至少一个原子,原子是具有mix()能力的一个对象;

2、宿主(host),一个系统有一个依赖的宿主,表明系统的外部环境,系统只是其宿主环境中的部分内容,可以由特定的名称来区别于其它;

3、种子(seed),一个系统诞生自一个种子,种子描述系统上述的meta和host两个方面的特性。

kissy约定,一个系统诞生自一个种子,该种子通过不停地mix()而成长,变成一个复杂的系统。由种子培育成为系统的整个环境,只需要能够理解mix与host,即可以基于seed来构建任意复杂的系统。

上述的逻辑在kissy.js中,描述得相当简单:

[javascript] view plaincopy

  1. (function(host, S) {
  2. var meta = {
  3. mix: function(r, s, ov, wl) {
  4. ...
  5. }
  6. },
  7. // If KISSY is already defined, the existing KISSY object will not
  8. // be overwritten so that defined namespaces are preserved.
  9. seed = (host && host[S]) || {},
  10. // The host of runtime environment. specify by user‘s seed or <this>,
  11. // compatibled for  ‘<this> is null‘ in unknown engine.
  12. host = seed.__HOST || (seed.__HOST = host || {});
  13. // shortcut and meta for seed.
  14. S = host[S] = meta.mix(seed, meta, false);
  15. return S;
  16. })(this, ‘KISSY‘);

这个系统初始化的时候,传入host与host中的系统名S。对于kissy来说,host是当前的系统环境,这里的this值,可以是javascript引擎的global,或浏览器环境的window,或某个函数或对象闭包内的当前this。而‘KISSY‘值,表现kissy系统在环境中的名字。按照javascript的语言约定,我们可以通过host[S]来找到既已经存在的kissy系统。

按照此前的约定,一个mix构建的系统,必然有host和mix两个性质,因为它最原始的种子(seed)就必然包括这两种性质。所以,既然我们上面是通过host[S]来访问一个“既已存在的kissy系统”,则无论该kissy系统经过了何种程度的演化,必然会包括这两种性质。

上面的构建过程尝试寻找在host[S]中寻找这两种性质,如果其中之一不存在,则尝试初始化它。例如代码:

[javascript] view plaincopy

  1. seed = (host && host[S]) || {},

如果host[S]是存的,则假设它是一个seed,否则初始化为一个空的对象。接下来:

[javascript] view plaincopy

  1. host = seed.__HOST || (seed.__HOST = host || {})

如果上述的种子seed有host属性,则使用它既有的__HOST,如果没有,则置为当前环境下的host,或一个空的对象。

现在我们看到的seed,必然已经具有host属性。但是,它还“可能”缺少一个性质,即最最重要的mix()。mix()的作用其实很简单,就是从对象B将属性抄写到对象A的一个方法。而这里,之所以说是“可能”缺少,是因为如果seed是既有的mix系统,则他已经有mix()属性;如果它是第三方系统,则可能没有mix,或有一个不同的mix等等。下面的一行代码尝试用元语言的思想构建它,即:

[javascript] view plaincopy

  1. meta.mix(seed, meta, false);  // false值表明不覆盖

元语言的特点是自描述的,meta.mix()可以向seed混入mix(),也可以使seed.mix()能混入其它系统或meta本身。总之在mix()的构建中,meta只需要有mix这个方法,不需要更多,也不能更少。

上一行代码的结果,是:如果seed没有自已的mix()属性,则向seed混入meta的原始的mix()。

现在,我们再看seed,必然已经具有了host和mix()属性。它本身可能是一个空对象,也可能是一个庞大的既有系统,但无论如此,它具有了这两个性质,就可以作为seed进一步的衍生。

在这一切之前,下面的代码保证它位于HOST[S],并返回这个系统:

[javascript] view plaincopy

  1. S = host[S] = meta.mix(seed, meta, false);
  2. return S;

 

三、mix()系统构建中的其它概念

 

kissy除了实现基本的mix系统之外,在core部分加入了其它的一些功能。包括除mix()之外的两种混入方法:

augment,扩充。用mix方法,将另一些子系统s[i]的原型,混入目标子系统r的原型。

merge,合并。用mix方法,将另一些子系统s[i],混入当前子系统S。

基本上来说,augment是通过mix来对javascript的原型系统进行扩充的方法,或是在应用系统中,结合原型机制与混入机制来构建系统。而merge只是mix方法的一个批量工具。

另外,考虑到面向对象系统中的继承特性,kissy也实现了extend(派生)方法,以提供传统的面向对象编程能力。

除了语言级别的概念之外,kissy也提供系统框架级别的一些构建能力。包括:

app,应用。与host[S]并列的,具有同等能力的其它应用,app(‘XXX‘, ...)可以在host[‘XXX‘]上组织应用。

namespace,命名空间。即可以组织出host[XXX].YYY.ZZZ这样的,在不同子系统中的,不同命名空间下的系统。

最后,kissy在内核中也提供简单的调试支持。

显然的,基于mix的原则,任何一个第三方的系统可以通过混入kissy来修改上述的概念,例如覆盖extend()来实现自己的对象系统构建原则,或覆盖app()来实现自己的应用组织原则。第三方系统也可以将kissy混入自身,在保障自身特性的情况下,使用kissy,以及更大规模的kissy ui系统带来的好处。

 

四、一点点提示

 

kISSY是什么?

KISSY是一个开源的javascript项目,其主体是一个前端UI开发框架,即KissyUI。本文所述的kissy是仅指其内核部分的kissy.js中的语言与框架设计思想。KISSY项目的开源网站是:http://kissyteam.github.com/

kissy怎么使用呢?

尽管在KissyUI向kissy内核化的过程中,我们提出了一些新的概念与框架模型,但事实上,我们并未改变KissyUI的任何使用惯例。从代码上来看,kissy.js和lang.js以后的其它模块,并没有任何的变化,因此如果仅是将kissy当成一个UI系统来使用,你可以参考上面的开源网站,其中既有的KissyUI文档是完全有效的,而且KissyUI本身也是一个优秀的、便捷的Web UI框架。但是,kissy系统在模向合并和组织上的能力大大增强了。例如说,我们可以开始想象下面这样的代码:

[xhtml] view plaincopy

  1. <!-- 先装载jQuery -->
  2. <script src="jQuery.js" mce_src="jQuery.js"></script>
  3. <!-- 将jQuery系统映射到KISSY,作为初始的seed -->
  4. <script type="text/javascript">
  5. window.KISSY = jQuery;
  6. </script>
  7. <!-- 装载kissy,在jQuery上混入KISSY -->
  8. <script src="kissy.js"></script>
  9. <script type="text/javascript">
  10. document.writeln(‘你现在使用的是Kissy,还是jQuyer?答案请选Y,或者Y‘);
  11. document.writeln(‘你现在能装载Kissy UI,还是jQuery UI?答案请选Y,或者Y‘);
  12. KISSY.merge(YUI, Dojo, Qomo).merge(Biby);
  13. document.writeln("what‘s KISSY? select collapsar or black hole, pls

继承与混合,略谈系统的构建方式,布布扣,bubuko.com

时间: 2024-12-18 03:14:23

继承与混合,略谈系统的构建方式的相关文章

略谈SQL中的存储过程

对于数据库,一直在增,删,查,改这四个操作中转悠徘徊,没去想太多数据其他的东西.最近发现数据库中等待发现的,等待学习的,等待挖掘的东西太多了.我一直没去搞清楚游标,存储过程以及触发器等等这些知识概念,从没有想过数据库的优化工作和代码简化工作. 之前写了一篇关于数据库的触发器,这一篇主要谈一下数据库的存储过程. 首先SQL Server支持5种类型的存储过程: 系统存储过程,本地存储过程,临时存储过程,远程存储过程,扩展存储过程 1.系统存储过程:由系统提供的存储过程,可以作为命令执行各种操作.系

Cocos2d-x v3.1 GUI系统--环境构建(七)

Cocos2d-x v3.1 GUI系统--环境构建(七) 在使用Cocos2d-x的GUI系统时,由于生成的工程默认是没有将GUI系统所需的库导入到项目的,所以我们必须把库导入到工程中并对工程做一些配置才能够使用GUI系统.这篇文章我们先在配置Windows上的环境,并对GUI系统中的组织结构进行一个介绍,然后我们会写一个简单的Demo来测试我们配置的环境,最后我们配置Android环境,同样的也是通过此Demo进行测试. Windows平台环境配置 在工程目录下,我们先找到所依赖的库.GUI

Delcam PowerShape 2015 R2 SP3 Win32_64 1CD三合一混合造型设计系统

Delcam PowerShape 2015 R2 SP3 Win32_64 1CD三合一混合造型设计系统 PowerSHAPE Pro 是 Delcam 三维 CAD 的旗舰产品,采用世界首个 Tribrid Modelling 三合一造型技术,将实体.曲面和三角形造型建模技 术相结合,为工业创新设计提供独特而强大的工具.PowerSHAPE Pro 可广泛应用于各个领域的 CAD 设计,尤其适合于工业产品的概念设计.创新设计. Delcam Crispin ShoeCost 2015 R2

评分卡系列(一):讲讲评分系统的构建

作者:JSong 时间:2017.12 我想通过几篇文章,给评分卡的全流程一个中等粒度的介绍.另外我的本职工作不是消费金融的数据分析,所以本系列的文章会偏技术一些. 数据分析工具主要有Python3及pandas.sklearn等科学计算包,另外也会有自己的工具包reportgen. 信用记录数据采用Lending Club的公开数据,特征数目和样本数都比较理想.大家可以到官网(www.lendingclub.com)下载,或者关注我的微信公众号后台回复:?数据集 ? 下载(含变量介绍和中文对照

秒杀系统的思考方式与设计思路--左手隔离,右手分层

大家好,我是崔皓. 很高兴有这样一个机会和大家认识.我在IT行业从事软件开发工作十余年了,足迹涵盖企业服务,互联网,企业数字化转型等.工作之余热爱阅读和学习,希望能通过这个专栏和大家成为朋友. 开篇 本次专栏要给大家分享的是"如何设计秒杀系统",专栏共包括15章,本章是第一章.今天会给大家介绍以下内容: 秒杀场景的特征 隔离的设计思路 分层设计思路本章的讲解思路是,提出秒杀场景的特征,也就是理解什么是秒杀.然后介绍在秒杀系统设计的底线,有了底线才能保证进可攻退可守.最后介绍使用哪些方法

【Mac双系统设置系统默认启动系统】解决方式

解决方式1: 开机时长按option键,进入系统选择界面: 用左右方向键选择到你要设置为默认启动的盘, 然后同一时候按下ctrl+enter键.就可以将其设置为默认启动的系统. 解决方式2: 选择mac系统进入后, 点击 系统偏好设置----->启动磁盘----->进入例如以下图界面: 首先点击最以下的锁图片.然后再进行更改, 选择你要设置为默认启动的系统后,点击又一次启动button生效.

变种 Builder 模式:优雅的对象构建方式

读完本文你将了解到: 帅气的 Builder 链式调用 常见的两种构建方式 常见的构建方式之一定义多个重载的构造函数 常见的构建方式之二使用 setter 方法挨个构造 优雅的构建方式变种 Builder 模式 Android Studio 中使用插件自动生成 变种 Builder 模式代码 总结 Thanks 帅气的 Builder 链式调用 在日常开发中,经常可以看到这样的代码: Retrofit retrofit = new Retrofit.Builder() .baseUrl("htt

浅谈尾递归的优化方式

尾递归与Continuation 浅谈尾递归的优化方式

jenkins介绍部署及三种构建方式配置

[隐藏] 1前言 1.1jenkins介绍 1.2jenkins好处 1.3我的jenkins实践 1.4jenkins使用前提 2jenkins部署 2.1下面内容介绍 2.2环境介绍 2.3jenkins安装 3插件安装 3.1手动下载jenkins插件 4Jenkins密钥配置 5jenkins触发式构建 6jenkins参数化构建 7jenkins定时构建 8Jenkins用户权限设置 8.1新创建一个用户 8.2用户权限设置 1.前言 1.1.jenkins介绍 jenkins是基于j