甚么是反弹表达式?
我们绕点青路来提问那个问题。
程式设计分成三类:控制系统程式设计(system programming)和应用领域程式设计(application programming)。简而言之控制系统程式设计,单纯而言,是撰写库;而应用领域程式设计是借助写好的各式各样程序库撰写具这种不足含意的流程,也是应用领域。控制系统开发人员会给他们写的库遗留下一些USB,即API(application programming interface,应用领域程式设计USB),以供给用领域开发人员使用。所以在抽象化层的库尔里,库坐落于应用领域的里边。
当流程跑起来时,一般情况下,应用领域流程(application program)easier通过API初始化莫拉所事先底上的表达式。但很多库表达式(library function)却明确要求应用领域先传予它两个表达式,好在最合适的时候初始化,以顺利完成最终目标各项任务。那个被传至的、后又被初始化的表达式就称作反弹表达式(callback function)。
维米县,有一间旅店提供更多惊醒服务项目,但明确要求乘客他们下定决心惊醒的形式。能是打酒店客房电话号码,也能是派服务项目生去转过身,闲死怕耽搁事的,还能明确要求往他们身上浇盆水。这里,“惊醒”那个犯罪行为是旅店提供更多的,相等于库表达式,但惊醒的形式是由乘客下定决心并说旅店的,也是反弹表达式。而乘客说旅店怎么惊醒他们的姿势,也是把反弹表达式传至库表达式的姿势,称作注册登记反弹表达式(to register a callback function)。如下表所示斑蛛属

能看见,反弹表达式一般而言和应用领域处在同两个抽象化层(因为传至甚么样的反弹表达式是在应用领域等级下定决心的)。而反弹就成了两个高层人士初始化下层,下层再再来初始化高层人士的操作过程。(我认为)这如果是反弹最早的应用领域含意,也是其闻名于世这般的其原因。
反弹监督机制的竞争优势
从下面的范例能看出,反弹监督机制提供更多了非常大的灵活性。请注意,从现在开始,我们把图中的库表达式改称作中间表达式了,这是因为反弹并不仅仅用在应用领域和库之间。任何时候,只要想获得类似于下面情况的灵活性,都能借助反弹。
这种灵活性是怎么实现的呢?乍看起来,反弹似乎只是表达式间的初始化,但仔细一琢磨,能发现两者之间的两个关键的不同:在反弹中,我们借助这种形式,把反弹表达式像参数一样传至中间表达式。能这么理解,在传至两个反弹表达式之前,中间表达式是不完整的。换句话说,流程能在运行时,通过注册登记不同的反弹表达式,来下定决心、改变中间表达式的犯罪行为。这就比单纯的表达式初始化要灵活太多了。请看下面这段Python写成的反弹的单纯示例:
`even.py`
`callback_demo.py`
运行`callback_demp.py`,输出如下表所示:
下面的代码里,给`getOddNumber`传至不同的反弹表达式,它的表现也不同,这是反弹监督机制的竞争优势所在。值得一提的是,下面的第三个反弹表达式是两个匿名表达式。
易被忽略的第三方
通过下面的论述可知,中间表达式和反弹表达式是反弹的两个必要部分,不过人们往往忽略了反弹里的第三位要角,是中间表达式的初始化者。绝大多数情况下,那个初始化者能和流程的主表达式等同起来,但为了表示区别,我这里把它称作起始表达式(如下面的代码中注释所示)。
之所以特意强调那个第三方,是因为我在网上读相关文章时得到一种印象,很多人把它单纯地理解为两个个体之间的来反弹用。譬如,很多中文网页在解释“反弹”(callback)时,都会提到这么一句话:“If you call me, I will call you back.”我没有查到这句英文的出处。我个人揣测,很多人把起始表达式和反弹表达式看作为一体,大概有两个其原因:第一,可能是“回调”这一名字的误导;第二,给中间表达式传至甚么样的反弹表达式,是在起始表达式里下定决心的。实际上,反弹并不是“你我”两方的互动,而是ABC的三方联动。有了那个清楚的概念,在他们的代码里实现反弹时才不容易混淆出错。
另外,反弹实际上有两种:阻塞式反弹和延迟式反弹。两者的区别在于:阻塞式反弹里,反弹表达式的初始化一定发生在起始表达式返回之前;而延迟式反弹里,反弹表达式的初始化有可能是在起始表达式返回之后。这里不打算对这两个概率做更深入的讨论,之所以把它们提出来,也是为了说明强调起始表达式的重要性。网上的很多文章,提到这两个概念时,只是笼统地说阻塞式反弹发生在主调表达式返回之前,却没有明确那个主调表达式到底是起始表达式还是中间表达式,不免让人糊涂,所以这里特意说明一下。另外还请注意,本文中所举的示例均为阻塞式反弹。延迟式反弹一般而言牵扯到多线程,我他们还没有完全搞明白,所以这里就不多说了。