回调函数
回调函数或简称回调(callback),是计算机编程中对某一段可执行代码的引用,它被作为參數传递给另一段代码;预期这段代码将回调(执行)这个回调函数作为自己工作的一部份。这种执行可以是即时的,如在同步回调之中;也可以在后来的时间点上发生,如在异步回调之中。
编程语言以不同方式支持回调,经常将它们实现为子例程、lambda表达式、块或函数指针。
使用
回调的用途十分广泛。例如,假设有一个函数,其功能为读取配置文件并由文件内容设置对应的选项。若这些选项由散列值所标记,则让这个函数接受一个回调会使得程序设计更加灵活:函数的调用者可以使用所希望的散列算法,该算法由一个将选项名转变为散列值的回调函数实现;因此,回调允许函数调用者在运行时调整原始函数的行为。
回调的另一种用途在于处理信号或者类似物。例如一个POSIX程序可能在收到SIGTERM信号时不愿立即终止;为了保证一切运行良好,该程序可以将清理函数注册为SIGTERM信号对应的回调。
回调亦可以用于控制一个函数是否作为:Xlib允许自定义的谓词用于决定程序是否希望处理特定的事件。
例子
下列C语言代码描述了利用回调处理POSIX风格的信号(在本示例中为SIGUSR1)的过程。值得注意的是,在处理信号的过程中,调用printf(3)
是不安全的。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sig(int signum)
{
printf("Received signal number %d!\n", signum);
}
int main(int argc, char *argv[])
{
signal(SIGUSR1, sig);
pause();
return 0;
}
系统调用pause(3)
会导致这个例子不做任何有意义的事,但这样做可以给你充分的时间来给这个进程发送信号。(在类Unix系统上,可以调用kill -USR1 <pid>
,其中<pid>
代表该程序的进程号。运行之后,该程序应当会有反应。)
实现
回调的形式因程序设计语言而有差别。
- Objective-C中允许利用@selector关键字传递SEL类型的函数名。在实现中,SEL类型被定义为函数名字符串。
- .NET语言中用到的事件与事件处理函数提供了用于回调的通用语法。
- 在缺少函数类型的参数的面向对象的程序语言中,例如Java,回调可以用传递抽象类或接口来模拟。回调的接收者会调用抽象类或接口的方法,这些方法由调用者提供实现。这样的对象通常是一些回调函数的集合,同时可能包含它所需要的数据。这种方法在实现某些设计模式时比较有用,例如访问者模式,观察者模式与策略模式。
参见
参考资料
- ^ Perl Cookbook - 11.4. Taking References to Functions. [2008-03-03]. (原始内容存档于2008-04-10).
- ^ Advanced Perl Programming - 4.2 Using Subroutine References. [2008-03-03]. (原始内容存档于2008-07-05).