Что такое функция обратного вызова? - PullRequest
630 голосов
/ 05 мая 2009

Что такое функция обратного вызова?

Ответы [ 21 ]

15 голосов
/ 05 мая 2009

Функция обратного вызова - это функция, которую вы указываете существующей функции / методу, которая вызывается, когда действие завершено, требует дополнительной обработки и т. Д.

В Javascript или, более конкретно, в jQuery, например, вы можете указать аргумент обратного вызова, который будет вызываться после завершения анимации.

В PHP функция preg_replace_callback() позволяет предоставить функцию, которая будет вызываться при сопоставлении регулярного выражения, передавая строку (строки), совпадающую в качестве аргументов.

13 голосов
/ 11 мая 2015

Что такое обратный вызов ?

  • В общем, был сделан телефонный звонок, чтобы вернуть тот, который кто-то получил.
  • В вычислениях обратный вызов - это фрагмент исполняемого кода, который передается в качестве аргумента другому коду. Когда функция завершает свою работу (или когда происходит какое-то событие), она вызывает функцию обратного вызова (она перезванивает вам - отсюда и имя).

Что такое функция обратного вызова ?

  • функция обратного вызова подобна Слуге, который «перезванивает» своему Мастеру, когда он завершил задачу.
  • a функция обратного вызова - это функция, которая передается другой функции (давайте назовем эту другую функцию otherFunction) в качестве параметра, и функция обратного вызова вызывается (или выполняется) внутри otherFunction ,
    function action(x, y, callback) {
        return callback(x, y);
    }

    function multiplication(x, y) {
        return x * y;
    }

    function addition(x, y) {
        return x + y;
    }

    alert(action(10, 10, multiplication)); // output: 100

    alert(action(10, 10, addition)); // output: 20

В SOA обратный вызов позволяет подключаемым модулям получать доступ к сервисам из контейнера / среды.

Аналогия: Обратные вызовы. Асинхронный. Неблокируемая
Реальный пример обратного вызова

10 голосов
/ 23 декабря 2011

посмотрите на изображение:) this is how it works

Основная программа вызывает библиотечную функцию (которая также может быть функцией системного уровня) с именем функции обратного вызова. Эта функция обратного вызова может быть реализована несколькими способами. Основная программа выбирает один обратный вызов согласно требованию.

Наконец, библиотечная функция вызывает функцию обратного вызова во время выполнения.

6 голосов
/ 10 марта 2011

Простой ответ на этот вопрос заключается в том, что функция обратного вызова - это функция, которая вызывается через указатель на функцию. Если вы передаете указатель (адрес) функции в качестве аргумента другому, когда этот указатель используется для вызова функции, на которую он указывает, говорят, что обратный вызов сделан

6 голосов
/ 04 мая 2013

Предположим, у нас есть функция sort(int *arraytobesorted,void (*algorithmchosen)(void)), где она может принять указатель функции в качестве аргумента, который может быть использован в некоторый момент реализации sort(). Затем здесь код, к которому обращается указатель функции algorithmchosen, называется функцией обратного вызова .

И видим преимущество в том, что мы можем выбрать любой алгоритм, например:

  1.    algorithmchosen = bubblesort
  2.    algorithmchosen = heapsort
  3.    algorithmchosen = mergesort   ...

Которые, скажем, были реализованы с помощью прототипа:

  1.   `void bubblesort(void)`
  2.   `void heapsort(void)`
  3.   `void mergesort(void)`   ...

Это концепция, используемая для достижения полиморфизма в объектно-ориентированном программировании.

3 голосов
/ 16 мая 2017

«В компьютерном программировании обратный вызов - это ссылка на исполняемый код или фрагмент исполняемого кода, который передается в качестве аргумента другому коду. Это позволяет программному уровню более низкого уровня вызывать подпрограмму (или функцию), определенную в более высоком уровне ». - Википедия

Обратный вызов в C с использованием указателя функции

В C обратный вызов реализован с использованием указателя функций. Указатель на функцию - как следует из названия, является указателем на функцию.

Например, int (* ptrFunc) ();

Здесь ptrFunc - указатель на функцию, которая не принимает аргументов и возвращает целое число. НЕ забывайте ставить в круглые скобки, иначе компилятор будет считать, что ptrFunc - это обычное имя функции, которое ничего не берет и возвращает указатель на целое число.

Вот некоторый код для демонстрации указателя функции.

#include<stdio.h>
int func(int, int);
int main(void)
{
    int result1,result2;
    /* declaring a pointer to a function which takes
       two int arguments and returns an integer as result */
    int (*ptrFunc)(int,int);

    /* assigning ptrFunc to func's address */                    
    ptrFunc=func;

    /* calling func() through explicit dereference */
    result1 = (*ptrFunc)(10,20);

    /* calling func() through implicit dereference */        
    result2 = ptrFunc(10,20);            
    printf("result1 = %d result2 = %d\n",result1,result2);
    return 0;
}

int func(int x, int y)
{
    return x+y;
}

Теперь давайте попробуем понять концепцию обратного вызова в C, используя указатель на функцию.

Полная программа имеет три файла: callback.c, reg_callback.h и reg_callback.c.

/* callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* callback function definition goes here */
void my_callback(void)
{
    printf("inside my_callback\n");
}

int main(void)
{
    /* initialize function pointer to
    my_callback */
    callback ptr_my_callback=my_callback;                        
    printf("This is a program demonstrating function callback\n");
    /* register our callback function */
    register_callback(ptr_my_callback);                          
    printf("back inside main program\n");
    return 0;
}

/* reg_callback.h */
typedef void (*callback)(void);
void register_callback(callback ptr_reg_callback);


/* reg_callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* registration goes here */
void register_callback(callback ptr_reg_callback)
{
    printf("inside register_callback\n");
    /* calling our callback function my_callback */
    (*ptr_reg_callback)();                               
}

Если мы запустим эту программу, вывод будет

Это программа, демонстрирующая функцию обратного вызова. внутри register_callback внутри my_callback обратно в основную программу

Функция верхнего уровня вызывает функцию нижнего уровня как обычный вызов, а механизм обратного вызова позволяет функции нижнего уровня вызывать функцию верхнего уровня через указатель на функцию обратного вызова.

Обратный вызов в Java с использованием интерфейса

В Java нет понятия указателя на функцию Он реализует механизм обратного вызова через механизм интерфейса Здесь вместо указателя на функцию мы объявляем интерфейс, имеющий метод, который будет вызван, когда вызываемый объект завершит свою задачу

Позвольте мне продемонстрировать это на примере:

Интерфейс обратного вызова

public interface Callback
{
    public void notify(Result result);
}

Абонент или класс более высокого уровня

public Class Caller implements Callback
{
Callee ce = new Callee(this); //pass self to the callee

//Other functionality
//Call the Asynctask
ce.doAsynctask();

public void notify(Result result){
//Got the result after the callee has finished the task
//Can do whatever i want with the result
}
}

Функция Callee или нижнего уровня

public Class Callee {
Callback cb;
Callee(Callback cb){
this.cb = cb;
}

doAsynctask(){
//do the long running task
//get the result
cb.notify(result);//after the task is completed, notify the caller
}
}

Обратный вызов с использованием шаблона EventListener

  • Элемент списка

Этот шаблон используется для уведомления от 0 до n номеров Наблюдателей / Слушателей о том, что конкретное задание завершено

  • Элемент списка

Разница между механизмом обратного вызова и механизмом EventListener / Observer заключается в том, что при обратном вызове вызываемый абонент уведомляет единственного вызывающего абонента, тогда как в Eventlisener / Observer вызываемый может уведомить любого, кто заинтересован в этом событии (уведомление может перейти к другому части приложения, которые не вызвали задачу)

Позвольте мне объяснить это на примере.

Интерфейс событий

public interface Events {

public void clickEvent();
public void longClickEvent();
}

Виджет класса

package com.som_itsolutions.training.java.exampleeventlistener;

import java.util.ArrayList;
import java.util.Iterator;

public class Widget implements Events{

    ArrayList<OnClickEventListener> mClickEventListener = new ArrayList<OnClickEventListener>(); 
    ArrayList<OnLongClickEventListener> mLongClickEventListener = new ArrayList<OnLongClickEventListener>();

    @Override
    public void clickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnClickEventListener> it = mClickEventListener.iterator();
                while(it.hasNext()){
                    OnClickEventListener li = it.next();
                    li.onClick(this);
                }   
    }
    @Override
    public void longClickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnLongClickEventListener> it = mLongClickEventListener.iterator();
        while(it.hasNext()){
            OnLongClickEventListener li = it.next();
            li.onLongClick(this);
        }

    }

    public interface OnClickEventListener
    {
        public void onClick (Widget source);
    }

    public interface OnLongClickEventListener
    {
        public void onLongClick (Widget source);
    }

    public void setOnClickEventListner(OnClickEventListener li){
        mClickEventListener.add(li);
    }
    public void setOnLongClickEventListner(OnLongClickEventListener li){
        mLongClickEventListener.add(li);
    }
}

Кнопка класса

public class Button extends Widget{
private String mButtonText;
public Button (){
} 
public String getButtonText() {
return mButtonText;
}
public void setButtonText(String buttonText) {
this.mButtonText = buttonText;
}
}

Флажок класса

public class CheckBox extends Widget{
private boolean checked;
public CheckBox() {
checked = false;
}
public boolean isChecked(){
return (checked == true);
}
public void setCheck(boolean checked){
this.checked = checked;
}
}

Класс занятий

пакет com.som_itsolutions.training.java.exampleeventlistener;

public class Activity implements Widget.OnClickEventListener
{
    public Button mButton;
    public CheckBox mCheckBox;
    private static Activity mActivityHandler;
    public static Activity getActivityHandle(){
        return mActivityHandler;
    }
    public Activity ()
    {
        mActivityHandler = this;
        mButton = new Button();
        mButton.setOnClickEventListner(this);
        mCheckBox = new CheckBox();
        mCheckBox.setOnClickEventListner(this);
        } 
    public void onClick (Widget source)
    {
        if(source == mButton){
            mButton.setButtonText("Thank you for clicking me...");
            System.out.println(((Button) mButton).getButtonText());
        }
        if(source == mCheckBox){
            if(mCheckBox.isChecked()==false){
                mCheckBox.setCheck(true);
                System.out.println("The checkbox is checked...");
            }
            else{
                mCheckBox.setCheck(false);
                System.out.println("The checkbox is not checked...");
            }       
        }
    }
    public void doSomeWork(Widget source){
        source.clickEvent();
    }   
}

Другой класс

public class OtherClass implements Widget.OnClickEventListener{
Button mButton;
public OtherClass(){
mButton = Activity.getActivityHandle().mButton;
mButton.setOnClickEventListner(this);//interested in the click event                        //of the button
}
@Override
public void onClick(Widget source) {
if(source == mButton){
System.out.println("Other Class has also received the event notification...");
}
}

Основной класс

public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Activity a = new Activity();
OtherClass o = new OtherClass();
a.doSomeWork(a.mButton);
a.doSomeWork(a.mCheckBox);
}
}

Как видно из приведенного выше кода, у нас есть интерфейс с названием events, который в основном перечисляет все события, которые могут произойти для нашего приложения. Класс Widget является базовым классом для всех компонентов пользовательского интерфейса, таких как Button, Checkbox. Эти компоненты пользовательского интерфейса являются объектами, которые фактически получают события из кода платформы. Класс Widget реализует интерфейс Events, а также имеет два вложенных интерфейса: OnClickEventListener & OnLongClickEventListener

Эти два интерфейса отвечают за прослушивание событий, которые могут произойти в компонентах пользовательского интерфейса, полученных из виджетов, таких как Button или Checkbox. Таким образом, если мы сравним этот пример с более ранним примером Callback с использованием интерфейса Java, эти два интерфейса будут работать как интерфейс Callback. Таким образом, код более высокого уровня (Здесь Activity) реализует эти два интерфейса. И всякий раз, когда событие происходит с виджетом, будет вызываться код более высокого уровня (или метод этих интерфейсов, реализованный в коде более высокого уровня, который здесь называется Activity).

Теперь позвольте мне обсудить основное различие между шаблоном Callback и Eventlistener. Как мы уже упоминали, используя Callback, Callee может уведомить только одного абонента. Но в случае шаблона EventListener любая другая часть или класс приложения может регистрироваться для событий, которые могут происходить на кнопке или флажке. Примером такого класса является класс OtherClass. Если вы увидите код OtherClass, вы обнаружите, что он зарегистрировал себя в качестве прослушивателя ClickEvent, что может происходить в кнопке, определенной в Activity. Интересно то, что помимо Activity (Вызывающий объект), этот OtherClass также будет уведомляться всякий раз, когда происходит событие нажатия кнопки.

2 голосов
/ 24 мая 2018

Функция обратного вызова - это функция, которую вы передаете (в качестве ссылки или указателя) определенной функции или объекту. Эта функция или объект будут вызывать эту функцию обратно в любое время, возможно, несколько раз, для любых целей:

  • уведомление о завершении задачи
  • запрос сравнения между двумя элементами (как в c qsort ())
  • отчет о ходе процесса
  • уведомляющие события
  • делегирование экземпляра объекта
  • делегирование картины области

...

Таким образом, описание обратного вызова как функции, вызываемой в конце другой функции или задачи, чрезмерно упрощается (даже если это общий случай использования).

1 голос
/ 26 апреля 2019

Обратный вызов - это идея передать функцию в качестве параметра другой функции и вызвать ее после завершения процесса.

Если вы получили концепцию обратного вызова через удивительные ответы выше, я рекомендую вам изучить основы этой идеи.

"Что заставило их (ученых-компьютерщиков) разработать обратный вызов?" Вы можете узнать проблему, которая блокирует (особенно блокирует пользовательский интерфейс) И обратный вызов - не единственное решение. Существует множество других решений (например, Thread, Futures, Promises ...).

1 голос
/ 08 января 2018

Функция обратного вызова Функция, переданная другой функции в качестве аргумента.

function test_function(){       
 alert("Hello world");  
} 

setTimeout(test_function, 2000);

Примечание: В приведенном выше примере test_function используется в качестве аргумента для функции setTimeout.

1 голос
/ 05 мая 2009

Одной из важных областей использования является то, что вы регистрируете одну из своих функций в качестве дескриптора (то есть обратного вызова), а затем отправляете сообщение / вызываете какую-то функцию для выполнения какой-либо работы или обработки. Теперь, когда обработка завершена, вызываемая функция будет вызывать нашу зарегистрированную функцию (т. Е. Теперь выполнен обратный вызов), что указывает на то, что обработка завершена.
Эта ссылка на википедию довольно хорошо объясняет графически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...