通俗易懂的让你彻底明白接口回调机制

理解接口回调:客户与厨师的合作模式
本文通过比喻解释接口回调的概念,使用客户与厨师的例子深入浅出地阐述了接口回调的机制,包括如何通过回调实现不同角色之间的交互与数据传递。详细介绍了接口、类与方法之间的相互调用过程,以及在实际应用中的常见场景。

转载请注明出处:flowsky37的博客,尊重他人辛苦劳动!
接口回调简单理解就是:类A中调用B类的中方法C,而B又反过去调用A中的方法D,然后D称为A的回调方法。是不是心中有一万只草泥马在奔腾,到底说的是什么。感觉像是你中有我,我中有你,纠缠不清。
举个通俗易懂的例子,比如顾客是A,厨师是B。面粉是接口Callback。然后面粉的吃法D是在顾客A的手中,厨师B有包子的做法C。现在需求是A有面粉,想吃包子,但是A是不会做包子,就需要去找厨师,让他调方法C做包子,A就把面粉Callback给了厨师,至于厨师怎么做,A不管,A只要你做好了给我一个结果(包子)就OK了。至于包子怎么吃,我是直接吃,还是蘸点醋吃,那是A的事了(A怎么吃的过程就是方法D里具体执行的代码)。
下面结合一个简单的例子看就容易多了。
首先是定义接口(面粉):

package com.example.interfacecallbackdemo;
public interface Callback {
    //因为是一堆面粉,肯定是没法吃的,所以没有具体的方法体,俗称“吃法”
    public void D(String result);
}
然后定义A类(客户):
package com.example.interfacecallbackdemo;
public class A implements Callback{
    /**
     * B类引用
     */
    private B b;
    public A(B b) {
        this.b = b;
    }
    /**
     * A类通过该方法调用B的方法C(可理解为找到厨师并将面粉给他)。
     */
    public void selectMenu(){
        b.C(this);
    }
    /**
     * A类中的D方法,也称为A类的回调方法(厨师做好包子将包子(result)返回给顾客A)
     */
    @Override
    public void D(String result) {
        System.out.print(result);
    }

}
然后是B类:
package com.example.interfacecallbackdemo;
public class B {
    /**
     * B类的C方法(接受面粉Callback,然后开工做包子,做好后返回给客户A)。
     */
    public void C(Callback callback){
        String result = "2";
        callback.D(result);
    }
}
再加上一个执行的对象,我是利用android中button调用的:
package com.example.interfacecallbackdemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{
    private A a;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_main)
        .setOnClickListener(this);
        a = new A(new B());
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_main:
            a.selectMenu();
            break;
        default:
            break;
        }

    }
}

(ABCD分别对应什么自己脑补,很easy吧)前面说的是A 调用B中的方法C,B又反过来调用A中的方法D。在代码中我就直接用ABCD ,简单、直接、粗暴。
但是,B类的C方法的参数不必一定要把Callback作为参数,如果C方法中没有这个参数,那在B类中一定要在其它地方把Callback接收进来。比如,我把B类稍微改动一下:

package com.example.interfacecallbackdemo;
public class B {
    private Callback callback;

    public B(Callback callback){
        this.callback = callback;
    }
    /**
     * B类的C方法
     */
    public void C(){
        String result = "2";
        callback.D(result);
    }
}

此时A类也要做相应的调整:

package com.example.interfacecallbackdemo;
import android.util.Log;
public class A {
    /**
     * B类引用
     */
    private B b;

    /**
     * A类同过该方法调用B类的C方法
     */
    public void selectMenu(){
        b = new B(new Callback() {

            @Override
            public void D(String result) {
                System.out.print(result);               
            }
        });
        b.C();
    }
}

呃,这个算是标准版的变异版,其实也是很简单的,毕竟这种可能是大家项目中实际中会见到而不至于弄不清楚,但是有一点,C方法中一定会有接口的实例对象调用其抽象方法。其实我们不需要按接口回调的定义去对比,重要的是理解其原理机制,只需记住,哪个类传递Callback实例对象过去的,就是我们所说的A,接受的就是B。
接口回调在android中是非常常见的,典型的就是各种监听器了,如果去分析下源码,你就会发现跟上面得那个例子大同小异。
上面是个人对接口回调的一些理解,如果有不明白的,可以留言;如果某些地方有误,非常欢迎指出,谢谢!**

<think>我们首先需要解释什么是回调函数,然后通过一个简单的例子来说明。 回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 通俗地说:回调函数就像是你给别人的一个电话号码,当对方有事情的时候就会打这个电话通知你。 举例:假设我们有一个排序函数,它可以对任何类型的数组进行排序,但是排序时需要比较两个元素的大小。由于不同的数据类型比较方式不同,我们可以让用户自己定义一个比较函数,然后将这个函数的指针传给排序函数。在排序过程中,排序函数会调用用户传入的比较函数来决定两个元素的顺序。 下面我们用C语言写一个例子: 我们实现一个冒泡排序函数,它可以对整数数组排序,但是排序的规则(升序或降序)由用户传入的回调函数决定。 步骤: 1. 定义一个函数指针类型,用于比较两个整数。 2. 实现冒泡排序函数,它接收一个整数数组、数组长度和一个比较函数的指针。 3. 在冒泡排序中,使用传入的比较函数来比较相邻的两个元素,以决定是否交换它们。 4. 用户定义两个比较函数:升序和降序。 5. 主函数中,分别用升序和降序的方式对数组进行排序并打印。 代码示例: ```c #include <stdio.h> // 定义函数指针类型,用于比较两个整数 typedef int (*CompareFunc)(int, int); // 冒泡排序函数,使用回调函数进行比较 void bubble_sort(int arr[], int n, CompareFunc comp) { for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-i-1; j++) { // 使用回调函数比较相邻元素 if (comp(arr[j], arr[j+1])) { // 交换 int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } // 升序比较:如果第一个数大于第二个数,则交换(即返回1表示需要交换,这样大的数就会往后移,最终达到升序) int ascending(int a, int b) { return a > b; } // 降序比较:如果第一个数小于第二个数,则交换(这样小的数就会往后移,最终达到降序) int descending(int a, int b) { return a < b; } // 打印数组 void print_array(int arr[], int n) { for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {64, 34, 25, 12, 22, 11, 90}; int n = sizeof(arr)/sizeof(arr[0]); printf("原始数组: "); print_array(arr, n); // 使用升序排序 bubble_sort(arr, n, ascending); printf("升序排序后: "); print_array(arr, n); // 重新初始化数组,因为上面已经排序过了 int arr2[] = {64, 34, 25, 12, 22, 11, 90}; n = sizeof(arr2)/sizeof(arr2[0]); // 使用降序排序 bubble_sort(arr2, n, descending); printf("降序排序后: "); print_array(arr2, n); return 0; } ``` 运行结果: 原始数组: 64 34 25 12 22 11 90 升序排序后: 11 12 22 25 34 64 90 降序排序后: 90 64 34 25 22 12 11 在这个例子中,bubble_sort函数是通用的排序函数,它通过回调函数comp来决定排序的规则。用户可以根据需要传入ascending或descending函数,从而实现不同的排序方式。 这就是回调函数的一个典型应用:将函数作为参数传递,使得函数更加灵活和可复用。 §§相关问题§§ 1. 回调函数在C语言中除了排序比较,还有哪些常见的应用场景? 2. 如何实现一个回调函数来处理不同的事件(例如事件驱动编程)? 3. 在C语言中,函数指针和普通指针有什么区别? 4. 回调函数在异步编程中是如何使用的? 5. 使用回调函数时需要注意哪些问题(比如内存安全、函数生命周期)?</think>### 通俗易懂讲解C语言回调函数(附示例) **回调函数本质**: 就像点外卖——你下单后(调用函数),把手机号留给商家(注册回调函数)。当外卖做好(事件发生),商家**回拨**你(执行回调函数)。核心是**"你定义函数,别人在特定时机调用"**。 #### 示例场景:计算器程序 假设我们要写一个计算器,能执行加、减、乘、除操作,但不想把每个运算都写死在主逻辑里。 ```c #include <stdio.h> // 1. 定义回调函数类型(函数指针) typedef int (*Operation)(int, int); // 2. 用户自定义的回调函数(加、减、乘) int Add(int a, int b) { return a + b; } int Subtract(int a, int b) { return a - b; } int Multiply(int a, int b) { return a * b; } // 3. 核心函数(接收回调函数作为参数) void Calculator(int x, int y, Operation op) { int result = op(x, y); // 在需要时执行回调 printf("结果: %d\n", result); } int main() { // 4. 传递不同回调函数实现不同功能 Calculator(10, 5, Add); // 输出:15 Calculator(10, 5, Subtract); // 输出:5 Calculator(10, 5, Multiply); // 输出:50 return 0; } ``` #### 关键比喻: - `Operation op` → **外卖订单**(约定回调格式) - `Add/Subtract` → **你的手机号**(具体回调函数) - `Calculator()` → **商家系统**(在合适时机回拨) - `op(x, y)` → **商家拨号动作**(执行回调) #### 实际应用场景: 1. **事件处理**:点击按钮时执行自定义函数 2. **排序算法**:qsort()中自定义比较规则 3. **异步通知**:网络下载完成后触发回调
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值