一、机制
回调函数是作为参数传递,或多或少类似于一个变量,期望在给定的时间回调(执行)该参数。
给定的时间:
- 同步回调:这种执行可能像在同步回调中一样是立即的
- 异步回调:也可能在稍后的时间像在异步回调中一样发生。
编程语言以不同的方式支持回调,通常用子程序、lambda表达式、块或函数指针来实现它们。
二、不同语言的实现
1.C/C++
C语言中回调函数主要通过函数指针的方式实现:
printHello
和printWorld
:回调函数是作为参数传递,或多或少类似于一个变量void (*callfunc)()
:只要自定义的函数(如printHello
和printWorld
)符合返回值和参数列表的类型要求,那么就可以随意传入自定义的函数。
(1)写法1:
//void要调用的函数的返回类型,(*callback_name)定式,(参数列表的类型)
void callback(void (*callfunc)())
{
//callback_name(传入的参数)
callfunc();
}
#include <stdio.h>
#include <stdlib.h>
void printHello()
{
printf("Hello!\n");
}
void printWorld()
{
printf("World!\n");
}
// 定义实现回调函数的"调用函数"
void callback(void (*callfunc)())
{
callfunc();
}
// 实现函数回调
int main(int argc, char* argv[])
{
callback(printHello);
callback(printWorld);
return 0;
}
/*
Hello!
World!
*/
(2)写法2:
//void要调用的函数的返回类型,(*callback_name)定式,(参数列表的类型)
typedef void (*callfunc)();
//callback_name arbitrary_name
void callback(callfunc p)
{
//arbitrary_name(传入的参数)
p();
}
#include <stdio.h>
#include <stdlib.h>
typedef void (*callfunc)();
void print()
{
printf("Hello World!\n");
}
// 定义实现回调函数的"调用函数"
void callback(callfunc p)
{
p();
}
// 实现函数回调
int main(int argc, char* argv[])
{
callback(print);
return 0;
}
(3)其他例子
#include <stdio.h>
int add(int a, int b, int(*callback)(int, int)) {
return callback(a,b);
}
int add(int a, int b) {
return a + b;
}
int main(int argc, char* args[]) {
int res = add(4, 2, add);
printf("%d\n", res);
return 0;
}
#include <stdio.h>
typedef int(*callback)(int, int);
int add(int a, int b, callback p) {
return p(a, b);
}
int add(int a, int b) {
return a + b;
}
int main(int argc, char* args[]) {
int res = add(4, 2, add);
printf("%d\n", res);
return 0;
}
可以看到algorithm的sort排序算法的实现,也是这个样子的
/*这里没有给出定义回调函数的"调用函数"sort的实现,可以到algorithm库查看该函数的定义*/
#include <stdio.h>
#include <algorithm>
// 回调函数的定义
bool cmp(int a, int b){
return a > b;
}
int main(void){
int a[8] = {5,43,1,7,8,13,0,74};
std::sort(a,a+10,cmp); // 回调函数的调用
return 0;
}
2.Java
Java通过接口类实现回调函数:用接口作为类型,传入实现类来达到“向上造型”的效果。
(1)匿名内部接口
interface MyInterface{
void func();
}
public class Shot {
public void callback(MyInterface myInterface) {
myInterface.func();
}
public static void main(String[] args) {
Shot shot = new Shot();
shot.callback(new MyInterface() {
@Override
public void func() {
// 回调函数
System.out.println("callback");
}
});
}
}
/*
callback
*/
在Android中按钮的点击用到了:https://blog.csdn.net/sandalphon4869/article/details/99741415#2_84
(2)接口实现
interface MyInterface{
void func();
}
public class Shot implements MyInterface{
public void callback(MyInterface myInterface) {
myInterface.func();
}
@Override
public void func() {
System.out.println("callback");
}
public static void main(String[] args) {
Shot shot = new Shot();
// 这个shot实现了MyInterface接口,重写了func()
shot.callback(shot);
}
}
/*
callback
*/
在Android中按钮的点击用到了:
https://blog.csdn.net/sandalphon4869/article/details/99741415#3_126
(3)代理模式
代理模式需要创建接口实现类,并放入代理类中,隔离性更好,扩展性好
interface MyInterface{
void func();
}
class Hello implements MyInterface{
@Override
public void func() {
System.out.println("hello");
}
}
class Hi implements MyInterface{
@Override
public void func() {
System.out.println("hi");
}
}
public class Shot {
public void callback(MyInterface myInterface) {
myInterface.func();
}
public static void main(String[] args) {
Shot shot = new Shot();
shot.callback(new Hello());
shot.callback(new Hi());
}
}
/*
hello
hi
*/
Reference: