引用
引用
这篇文章的宗旨是利用我们仅有的“宾谓”语法构造出完整的一套面向对象机制,所以更多代码在更多的时候是不应在实际工作中使用的(也算一种元语言抽象),所以类似效率、代码风格之类的问题反对回帖质疑。
四. 扩展的实现
上篇最后给出了一个“看上去很美”的基于消息传递的编程风格,比如构造一个 People 类的代码类似:
function People () {
var money = 0
function setMoney (dollars) {
money = dollars
}
function pay (dollars) {
money -= dollars
}
return (function (verb) {
return eval(verb)
})
}
有了这样的语法我们就可以描述不少句子了。但是存在一个问题:现实中的 Objects 之间是存在关系的——比如,forrest 是个 IQ 为 75 的傻子,傻子是 People 的一种。而我们仅仅是生搬硬套了一种语法而割裂了这种 "is-a" 关系。现在我们的工作,目的之一就是让这样一个“真切”的世界从我们已有的编程风格的地基上拔地而起。
到底应该怎样做才能使 Fool 产生的对象都能响应 People 的消息呢?我们要给 Fool 产生的对象(也就是返回的那个匿名函数啦)都添加这样一种能力:如果在 Fool 中响应不了消息,那就反馈给 People 响应。
function Fool (iq) {
var IQ = iq || 0
function init (iq) {
IQ = iq
}
return (function (verb) {
try {
return eval(verb)
} catch (e) {
return People()(verb)
}
})
}
js> forrest = Fool()
js> forrest('init')(75)
js> forrest('IQ')
75
js> forrest('money')
0
五. 语法扩展和代码生成
这下代码量增加了很多,强迫潜在的使用者们在创建每个类时都这样写那实在是令人抓狂。本来这篇文章应该不提此类问题的解决,但考虑到有益于读者理解“机制”这个抽象概念,这里给出一个可行的方案——把普通的类代码用 Function() 函数重编译为可用的 JavaScript 函数。也就是说,我们能给出类扩展的代码并指定被扩展的类来获取类似上文的代码:
Fool = extend('People()', function (iq){
var IQ = iq || 0
function init (iq) {
IQ = iq
}
})
为了方便字符串操作,我们希望编译后的代码的参数部分(如 People())都集中出现在一个位置且尽可能便于定位。在函数头添加一句
var origin = People()
当然是可行的,这样还能使 Fool 内部显式引用到其超类。但这样还不够漂亮。我们修改编译后的样例代码为:
function () {
return (function (origin) {
var IQ = 0
function init (iq) {
IQ = iq
}
return (function (verb) {
try {
return eval(verb)
} catch (e) {
return origin(verb)
}
})
})(People())
}
这个利用参数传递变量的小技巧不值得学习,实际效率不高。但在这篇文章中,这样绑定特殊变量的技术是标准方案。
那么,我们的语法扩展兼代码生成函数 extend() 的实现为:
function extend (originc, code) {
function argsArea (code) {
// 题外话,正则表达式也有不值得一用的时候
return code.slice(code.indexOf('(')+1, code.indexOf(')'))
}
function bodyCode (code) {
// 不用 trim() 了,别没事儿找事儿
return code.slice(code.indexOf('{')+1, code.lastIndexOf('}'))
}
function format (body) {
var objc = bodyCode(function () {
return (function (verb) {
try {
return eval(verb)
} catch (e) {
return origin(verb)
}
})
}.toString())
return 'return (function (origin) {'+body+objc+'})('+originc+')'
}
var $ = code.toString()
return Function(argsArea($), format(bodyCode($)))
}
这样前文提到过的 extend 的实例代码就可以正常运行了,测试代码不再重复。
六. 机制完备化
这样,我们的基于消息传递编程风格的一套面向对象机制就确定下来了。机制是宪法,是语言的根本大法,有了它,我们就可以通过修改代码生成器,很快地给这套机制进行完备化。
想法有很多,例子只举两个。
第一个例子:类的定义中应该能直接引用到将产生的对象 self。答案只有一句话:把返回的那个作为对象的匿名函数命名为 self。
第二个例子:既然是单继承模式,应当存在一个顶层类 AbsObj,使没有指定继承的类自动继承它。答案是:在 extend 函数体第一行添加代码:
if (arguments.length == 1) {
code = originc
originc = 'AbsObj()'
}
然后手工构造设计 AbsObj 类,为空也无所谓。不过当然了,一般都会给顶层类添加一些全局性质的消息绑定。由于是“底层操作”,基本上都需要修改 extend 函数。做了一个简单的:
function AbsObj () {
//检测是否能响应此 verb,要再用一次异常处理
function canHandle(verb){
try {
// 别担心这里的 self 会传递不过去
self(verb)
} catch (e) {
return false
}
return true
}
function toString() {} // 这个搞起来其实很麻烦~`
var self = function (verb) {
return eval(verb)
}
return self
}
js> Obj=extend(function(){x=5})
js> o=Obj()
js> o('canHandle')('x')
true
js> o('canHandle')('y')
false
文章写完了,小结一下。消息传递的编程不仅仅是一种代码风格,还可以成长为一种完备的机制。这种完备性远不只是这两篇加起来不到300行的文章所能覆盖的(例如非常彻底的“万物皆对象”,因为只要是能响应消息的函数,连接一下 AbsObj 就是合法对象了;类,函数都可以),大家可以试着玩一玩,顺便体会一下这个计算模型的透明和强大。
另外,熟悉函数式编程的朋友可以帮忙思考一下:这样一个基于闭包变换的计算模型实质上是函数式的,再配合动态的函数式的对象级继承(用一个匿名类代换一下)就能在纯 FP 真正下实现 OOP 了。可惜的是每一次更新操作都要重新生成对象,性能代价大了点,yet another question.
分享到:
相关推荐
针对上述问题,本文利用Java的接口、继承及多态机制,实现一种风格与微软基础类库中framework的消息机制相似的对象模型消息机制,将其应用于一款基于LEGO机器人的协同式智能化多机器人系统,结果证明该消息机制具有...
消息传递机制允许一个对象向另一个对象发送请求,后者根据接收到的消息执行相应的操作或返回信息。Java作为一种重要的编程语言,在标准中并未直接支持消息机制。虽然可以通过其他方式(如函数调用)来模拟消息机制,...
在N皇后问题中,回溯法通常采用深度优先搜索(DFS)的方式,从棋盘的第一行开始放置皇后,如果发现当前位置不可行,则回溯到上一行,改变皇后的位置,直至找到一个可行解。回溯法的关键在于剪枝,通过判断当前位置...
例如,当用户创建新文档时,创建模块可以发布一条消息到消息总线上,存储模块订阅此消息并接收文档进行保存;同样,检索模块可以订阅文档更新或查询请求的消息,以便在需要时提供服务。 文档版本控制是确保文档历史...
例如,可以利用REST风格构建对外的服务接口,而内部则采用消息传递机制来处理高并发任务。 #### 四、结论 综上所述,请求/响应、消息传递以及REST这三种架构风格各有优势和适用场景。开发者应根据项目的具体需求和...
"车窗防夹软件界面 控件颜色 子对话框 消息传递"这个标题涉及到的是汽车智能系统中的用户界面设计,特别是与交互性和反馈机制相关的元素。下面我们将深入探讨这些知识点。 首先,**车窗防夹功能** 是现代汽车安全...
当Windows应用程序接收到消息时,这些消息首先被传递给应用程序的消息循环。消息循环通过调用`GetMessage()`函数从消息队列中获取消息,然后通过`DispatchMessage()`函数将消息发送到相应的窗口过程(通常是指MFC...
在Windows操作系统中,消息...总之,Windows消息机制是构建用户界面的基础,理解并熟练掌握消息的产生、传递和处理对于Windows应用程序开发至关重要。通过深入学习和实践,我们可以创建出响应灵敏、功能丰富的GUI应用。
SAP消息输出涉及到将系统消息传递给用户的机制。这包括: 1. 屏幕输出:SAP GUI中,消息会直接显示在用户界面上。 2. 报表输出:通过打印或电子形式(如PDF)生成报表。 3. 邮件通知:系统可以配置为将消息自动发送...
### 创建一个窗体涉及的消息机制 在Windows编程中,创建一个窗体(窗口)涉及到...从注册窗口类到创建窗口,再到消息循环的实现,每一步都至关重要。理解这些基础知识对于开发高质量的Windows应用程序是非常有帮助的。
这个机制使得我们可以方便地在不同类之间传递数据,处理事件或响应用户操作。在"Qt不同类进行信号与槽建立,并传递参数"这个主题中,我们将深入探讨如何在Qt的不同类中设置信号和槽,以及如何通过它们来传递参数。 ...
以下是从提供的文件内容中提炼出的知识点,涵盖消息传递、集成样式、消息系统、消息通道、消息构造、消息路由等关键概念。 ### 消息传递与消息系统概念 #### 消息传递和消息系统的基本概念 - **消息传递**:消息...
这些特性使得函数式编程风格成为可能,但同样遵循值传递的原则,除非使用`ref`或`out`。 6. **性能影响**:值传递相比引用传递通常有更快的执行速度,因为它不需要额外的内存管理和引用跟踪。然而,对于大对象或...
1. 对Windows API的理解:熟悉Windows API的基本使用方法,特别是涉及到消息处理的相关函数。 2. 易语言语法:掌握易语言的编程规则和语法,包括如何声明函数、传递参数等。 3. 消息机制:理解Windows的消息队列和...
自定义SOAP消息主要涉及到在使用ASP.NET创建的XML Web服务中,如何控制SOAP消息的格式。SOAP(简单对象访问协议)是一种轻量级的、基于XML的协议,用于在Web服务中交换结构化和类型化的信息。SOAP消息通常包含一个...
在MFC中实现这种风格的控件,需要理解MFC的消息机制、控件的自绘技术、文档/视图架构以及控件的组织方式。 1. **消息机制**:MFC是基于Windows消息驱动的,控件的事件通过消息映射函数来处理。开发者需要在消息映射...
1. Objective-C语言概述:Objective-C是一种面向对象的编程语言,它基于C语言,并加入了Smalltalk风格的消息传递机制。这种语言是苹果公司为iOS和macOS开发应用的核心语言,直至Swift语言的推出。 2. C++与...