主流开发语言如何实现回调

回调函数是很多流行开发语言都支持的,本文介绍一下各种语言都是怎么支持回调函数的。

什么是回调函数

关于回调函数是什么,直接上一段引用:

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

英语不好的我也大概知道什么意思:回调函数是一个函数,这个函数能作为参数传给另一个函数,另一个函数内部可以执行它。这个定义应该是javascript对回调函数的定义,其他语言也一个意思。

下面就介绍一下各种开发语言如何实现回调函数的。

Javascript

回调函数,js肯定首当其冲,不多说,直接上代码。

1
2
3
4
5
6
7
function callback_fun() {
alert('hello, world.');
}
function func1(cbf) {
cbf();
}
func1(callback_fun);

回调函数有什么用处?我觉得就是用于应用解耦,便于遵循开闭原则进行代码开发。

做js开发的肯定用过jquery,jquery对回调函数应用到了令人发指的地步,可以说是无处不回调。看代码:

1
2
3
4
5
$(document).ready(function() {
$('#hello').click(function() {
alert('hello, world.');
});
});

三行代码,连用两个回调函数,不知道jquery除了回调还会什么。

Python

说js最擅长回调,python肯定第一个不服,就上面的例子,代码写的跟js一样多就算我输。

1
2
3
4
5
def callback_fun():
print 'hello, world.'
def func1(cbf):
cbf()
func1(callback_fun)

怎么样,是不是比js少。

C/C++

对于回调,C语言同样不甘示弱,但为什么有人对C的回调函数不理解呢?先看代码:

1
2
3
4
5
6
7
8
9
void callback_fun(int n) {
printf("hello, world. %d\n", n);
}
void func1(void cbf(int)) {
cbf(2);
}
main() {
func1(callback_fun);
}

上面例子除了由于c语言定义变量时要指定类型外,其他没有什么麻烦的,无非就是记住回调函数作为参数时的写法。但事实真的是这样么?接着修改例子func1:

1
2
3
4
5
void func1(void cbf(int)) {
void (*f)(int);
f = cbf;
f(2);
}

必须写成这样,如果写成void f(int)是不行的。这是由于c语言中函数在定义的时候默认就是指针,但在声明变量时需要显式说明(这样描述我自己都理解不了,以后再说吧)。所以正规的回调函数写法应该这样:

1
2
3
void func1(void (*cbf)(int)) {
(*cbf)(2);
}

但是这样写出来的回调函数却不符合我们平时写c代码的思维习惯,一般都是变量类型 变量名的形式。下面写一个符合正常习惯的回调例子。

1
2
3
4
5
6
7
8
9
10
11
typedef void (*CALLBACK)(int);
void cb_fun(int n) {
printf("%d\n", n);
}
void func2(CALLBACK cbf) {
CALLBACK f = cbf;
(*f)(4);
}
main() {
func2(cb_fun);
}

用了一下typedef就使代码顺畅多了。

Java

Java是不支持函数回调的,因为Java中就根本没有函数这一说,在C/C++中函数是必须定义在全局的,类中那是方法,Java是不允许在类之外定义别任何变量,包括函数。但是这不影响java中使用回调,且在java中回调无处不在。写个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Callback {
public void run() {
System.out.println("hello, world.");
}
}
public class Test {
public void start(Callback cb) {
cb.run();
}
public static void main() {
Test t = new Test();
Callback cb = new Callback();
t.start(cb);
}
}

怎么样,想到了什么?多线程类Thread。我们常说的java实现多线程的方式有两种一是继承Thread,二是实现Runnable,其本质就一种就是执行Thread的start方法。只不过一是调用的重写的run而二是回调的实现的run而已。

总结

以上是记录了我常用的开发语言的回调,以后用到别的语言再补充吧。