Che cos'è una funzione di richiamata?


685

Che cos'è una funzione di richiamata?


8
puoi trovare qui: stackoverflow.com/a/9652434/3343174 la migliore spiegazione sui callback
Fakher,


Guarda la seconda risposta per una spiegazione dettagliata
Donato

La migliore spiegazione del callback che abbia mai trovato su youtube.com/watch?v=xHneyv38Jro
Sameer Sinha

Risposte:


683

Gli sviluppatori sono spesso confusi da ciò che è un callback a causa del nome della dannata cosa.

Una funzione di callback è una funzione che è:

  • accessibile da un'altra funzione e
  • viene richiamato dopo la prima funzione se la prima funzione viene completata

Un bel modo di immaginare come funziona una funzione di callback è che è una funzione che viene " chiamata sul retro " della funzione in cui è passata.

Forse un nome migliore sarebbe una funzione "chiama dopo" .

Questo costrutto è molto utile per il comportamento asincrono in cui vogliamo che si verifichi un'attività ogni volta che un evento precedente viene completato.

pseudocodice:

// A function which accepts another function as an argument
// (and will automatically invoke that function when it completes - note that there is no explicit call to callbackFunction)
funct printANumber(int number, funct callbackFunction) {
    printout("The number you provided is: " + number);
}

// a function which we will use in a driver function as a callback function
funct printFinishMessage() {
    printout("I have finished printing numbers.");
}

// Driver method
funct event() {
   printANumber(6, printFinishMessage);
}

Risultato se hai chiamato event ():

The number you provided is: 6
I have finished printing numbers.

L'ordine dell'output qui è importante. Poiché le funzioni di richiamata vengono chiamate in seguito, "Ho finito di stampare i numeri" viene stampato per ultimo, non per primo.

I callback sono cosiddetti a causa del loro utilizzo con le lingue dei puntatori. Se non usi uno di questi, non cercare il nome "callback". Basta capire che è solo un nome per descrivere un metodo che viene fornito come argomento a un altro metodo, in modo tale che quando viene chiamato il metodo genitore (qualunque condizione, come un clic sul pulsante, un segno di spunta del timer, ecc.) E il suo corpo del metodo venga completato, viene quindi richiamata la funzione di callback.

Alcuni linguaggi supportano costrutti in cui sono supportati più argomenti della funzione di callback e vengono chiamati in base al modo in cui la funzione genitore viene completata (ovvero viene chiamato un callback nel caso in cui la funzione genitore venga completata correttamente, un altro viene chiamato nel caso in cui la funzione genitore generi un errore specifico, ecc.).


31
Il tuo esempio è fantastico ma non vedo perché la terminologia sia "callback". Quando viene significato "Richiama" significatoOfLife?
CodyBugstein,

4
Ciao a riguardo once its parent method completes, the function which this argument represents is then called. Quindi se la funzione viene passata ad un'altra funzione come argomento ma chiamata dal centro del runtime della funzione genitore come parent(cb) {dostuff1(); cb(); dostuff2()}allora non viene considerata una callbackfunzione?
Max Yari,

2
@MaxYari: IMHO, è ancora considerato come callback. La cosa importante qui è che la funzione parent utilizzerà in qualche modo la funzione di input (aka callback). Può essere chiamato nel mezzo o alla fine o se viene soddisfatta una condizione.
Kamran Bigdely,

12
@ 8bitjunkie grazie - ma dove viene invocato il metodo meaningOfLife nella funzione printANumber?
BKSpurgeon,

2
Questo non è affatto vero: "viene automaticamente invocato dopo che la prima funzione è stata completata". Non è necessario eseguire una richiamata, figuriamoci automaticamente. In effetti, non è raro che i callback vengano completati prima del completamento della funzione genitore. Non mi piace molto il modo in cui le persone descrivono i callback come funzioni che vengono eseguite "in seguito". È molto confuso per le persone che stanno imparando su di loro. In poche parole, i callback sono solo funzioni che vengono passate come argomenti ad altre funzioni. Periodo. Una spiegazione migliore includerebbe la spiegazione del PERCHÉ i callback sui riferimenti alle funzioni.
Giordania,

226

Definizione opaca

Una funzione di callback è una funzione fornita a un altro pezzo di codice, che consente di essere chiamato da quel codice.

Esempio contrastato

Perché vorresti farlo? Diciamo che c'è un servizio che devi invocare. Se il servizio ritorna immediatamente, devi solo:

  1. Chiamalo
  2. Aspetta il risultato
  3. Continua quando arriva il risultato

Ad esempio, supponiamo che il servizio fosse la factorialfunzione. Quando si desidera il valore di 5!, si invoca factorial(5)e si verificano i seguenti passaggi:

  1. La posizione di esecuzione corrente viene salvata (nello stack, ma non è importante)

  2. L'esecuzione viene consegnata a factorial

  3. Al factorialtermine, mette il risultato in un punto in cui è possibile raggiungerlo

  4. L'esecuzione torna al punto in cui si trovava [1]

Ora supponiamo che ci sia factorialvoluto molto tempo, perché gli stai dando enormi numeri e deve funzionare su qualche cluster supercalcolo da qualche parte. Supponiamo che ti aspetti che siano necessari 5 minuti per restituire il risultato. Potresti:

  1. Mantieni il tuo design ed esegui il tuo programma di notte quando dormi, in modo da non fissare lo schermo per metà del tempo

  2. Progetta il tuo programma per fare altre cose mentre factorialsta facendo le sue cose

Se scegli la seconda opzione, i callback potrebbero funzionare per te.

Design end-to-end

Per sfruttare un modello di callback, ciò che vuoi è poter chiamare factorialnel modo seguente:

factorial(really_big_number, what_to_do_with_the_result)

Il secondo parametro, what_to_do_with_the_resultè una funzione a cui si invia insieme factorial, nella speranza che factoriallo richiamerà sul suo risultato prima di tornare.

Sì, questo significa che factorialdeve essere stato scritto per supportare i callback.

Supponiamo ora di voler poter passare un parametro al callback. Ora non puoi, perché non lo chiamerai, lo factorialè. Quindi factorialdeve essere scritto per permetterti di passare i tuoi parametri e li consegnerà al tuo callback quando lo invoca. Potrebbe apparire così:

factorial (number, callback, params)
{
    result = number!   // i can make up operators in my pseudocode
    callback (result, params)
}

Ora che factorialconsente questo modello, il tuo callback potrebbe assomigliare a questo:

logIt (number, logger)
{
    logger.log(number)
}

e la tua chiamata factorialsarebbe

factorial(42, logIt, logger)

Cosa succede se si desidera restituire qualcosa da logIt? Bene, non puoi, perché factorialnon ti sta prestando attenzione.

Bene, perché non puoi factorialsemplicemente restituire ciò che restituisce il tuo callback?

Rendendolo non bloccante

Poiché l'esecuzione deve essere consegnata al callback al factorialtermine, in realtà non dovrebbe restituire nulla al chiamante. E idealmente, in qualche modo lancerebbe il suo lavoro in un altro thread / processo / macchina e ritornerebbe immediatamente in modo da poter continuare, forse qualcosa del genere:

factorial(param_1, param_2, ...)
{
    new factorial_worker_task(param_1, param_2, ...);
    return;
}

Questa ora è una "chiamata asincrona", il che significa che quando la chiami, ritorna immediatamente ma non ha ancora fatto il suo lavoro. Quindi hai bisogno di meccanismi per controllarlo e per ottenere il suo risultato quando è finito, e il tuo programma è diventato più complesso nel processo.

E a proposito, usando questo modello è factorial_worker_taskpossibile avviare il callback in modo asincrono e tornare immediatamente.

Allora cosa fai?

La risposta è rimanere all'interno del modello di callback. Ogni volta che vuoi scrivere

a = f()
g(a)

e fdeve essere chiamato in modo asincrono, invece scriverai

f(g)

dove gviene passato come callback.

Questo cambia radicalmente la topologia di flusso del tuo programma e richiede un po 'di tempo per abituarsi.

Il tuo linguaggio di programmazione potrebbe aiutarti molto dandoti un modo per creare funzioni al volo. Nel codice immediatamente sopra, la funzione gpotrebbe essere piccola come print (2*a+1). Se la tua lingua richiede che tu la definisca come una funzione separata, con un nome e una firma del tutto inutili, la tua vita diventerà spiacevole se usi questo schema molto.

Se, d'altra parte, la tua lingua ti consente di creare lambdas, allora sei in una forma molto migliore. Quindi finirai per scrivere qualcosa del genere

f( func(a) { print(2*a+1); })

che è molto più bello.

Come passare il callback

Come passeresti la funzione di callback factorial? Bene, potresti farlo in diversi modi.

  1. Se la funzione chiamata è in esecuzione nello stesso processo, è possibile passare un puntatore a funzione

  2. O forse vuoi mantenere un dizionario fn name --> fn ptrnel tuo programma, nel qual caso potresti passare il nome

  3. Forse la tua lingua ti consente di definire la funzione sul posto, possibile come lambda! Internamente sta creando una sorta di oggetto e passa un puntatore, ma non devi preoccuparti di questo.

  4. Forse la funzione che stai chiamando è in esecuzione su un computer completamente separato e la stai chiamando utilizzando un protocollo di rete come HTTP. È possibile esporre il callback come funzione richiamabile HTTP e passarne l'URL.

Ti viene l'idea.

Il recente aumento dei callback

In questa era del web in cui siamo entrati, i servizi che invochiamo sono spesso in rete. Spesso non abbiamo alcun controllo su tali servizi, ovvero non li abbiamo scritti, non li manteniamo, non possiamo assicurarci che funzionino o come si comportano.

Ma non possiamo aspettarci che i nostri programmi si blocchino mentre aspettiamo che questi servizi rispondano. Consapevole di ciò, i fornitori di servizi spesso progettano API utilizzando il modello di callback.

JavaScript supporta i callback molto bene, ad es. Con lambda e chiusure. E c'è molta attività nel mondo JavaScript, sia sul browser che sul server. Esistono persino piattaforme JavaScript sviluppate per dispositivi mobili.

Mentre avanziamo, sempre più di noi scriveranno codice asincrono, per il quale questa comprensione sarà essenziale.


1
Un concetto molto ben spiegato ..! :)
piyushGoyal

Grande spiegazione, +1.
Lingamurthy CS

1
Questa è la migliore risposta tra tutte le altre. Si prega di votarlo.
Abhishek Nalin,

3
Spiegato perfettamente e tutto è spiegato. Vorrei poterlo votare di nuovo.
Yogesh Yadav,

Sì, capisco come funzionano i lambas in javascript e ruby. E java 8 ma le vecchie versioni di java non usavano lambas e invece usavano le classi e vorrei sapere come funziona quel tipo di callback. Ancora una risposta superiore all'altra.
Donato,

97

Si noti che il callback è una parola.

La pagina di richiamata di Wikipedia lo spiega molto bene.

citazione dalla pagina di Wikipedia:

Nella programmazione del computer, un callback è un riferimento al codice eseguibile, o un pezzo di codice eseguibile, che viene passato come argomento ad altro codice. Ciò consente a un livello software di livello inferiore di chiamare una subroutine (o funzione) definita in un livello di livello superiore.


14
Bel modo di presentare una risposta.
Chathuranga Chandrasekara,

1
E questo porta anche alla risposta in modo diverso. Il sostantivo "callback" è quello che è stato "richiamato", allo stesso modo qualcosa che ha attraversato l'arresto è stato chiuso e qualcosa che è stato usato per accedere è un accesso.
Anonimo

22
Questo avrebbe potuto essere un commento - fondamentalmente è un link a Wikipedia
CodyBugstein l'

Wikipedia ha davvero alcune cose di programmazione davvero fantastiche nelle sue scoperte. Ho sempre pensato che il termine "callback" fosse meglio spiegato usando la frase "Ho intenzione di richiamare a ..."
Thomas

Grande spiegazione su javascriptissexy.com/…; che ripubblicherò qui; Una funzione di callback è una funzione che viene passata a un'altra funzione come parametro e la funzione di callback viene chiamata o eseguita all'interno dell'altra funzione. // Nota che l'elemento nel parametro del metodo click è una funzione, non una variabile. // L'articolo è una funzione di callback $ ("# btn_1"). Click (function () {alert ("Btn 1 Clicked" );}); Come vedi nell'esempio precedente, passiamo una funzione come parametro al metodo click per eseguirla -
MarcoZen

46

Una risposta da laici sarebbe che si tratta di una funzione che non viene chiamata dall'utente ma piuttosto dall'utente o dal browser dopo che si è verificato un determinato evento o dopo l'elaborazione di un codice.


42

Una funzione di callback dovrebbe essere chiamata quando viene soddisfatta una determinata condizione. Invece di essere chiamata immediatamente, la funzione di richiamata viene chiamata in un determinato momento in futuro.

In genere viene utilizzato all'avvio di un'attività che termina in modo asincrono (ovvero termina qualche tempo dopo il ritorno della funzione chiamante).

Ad esempio, una funzione per richiedere una pagina Web potrebbe richiedere al chiamante di fornire una funzione di richiamata che verrà chiamata al termine del download della pagina Web.


Nella tua prima frase, dici "...when a condition is met"ma ho pensato che i callback vengano chiamati quando la funzione genitore termina l'esecuzione e non dipendono dalle condizioni (?).
Ojonugwa Jude Ochalifu,

La "certa condizione" significa solo che vengono generalmente chiamati per un motivo, piuttosto che a caso. Un callback potrebbe essere chiamato quando il genitore / creatore sta ancora eseguendo - questo potrebbe portare a una condizione di competizione se il programmatore non se lo aspetta.
Thomas Bratt,

Ok, grazie per il chiarimento
Ojonugwa Jude Ochalifu,

34

I callback sono descritti più facilmente in termini di sistema telefonico. Una chiamata di funzione è analoga a chiamare qualcuno al telefono, farle una domanda, ottenere una risposta e riagganciare; l'aggiunta di una richiamata modifica l'analogia in modo che dopo averle fatto una domanda, le dia anche il tuo nome e numero in modo che possa richiamarti con la risposta.

- Paul Jakubik, "Implementazioni callback in C ++"


1
Quindi il mio nome e numero sono una funzione?
Koray Tugay,

No, sarebbe l'analogia se "callback" fosse un buon nome per ciò che è invece: chiedi all'operatore telefonico di effettuare una chiamata. La fine.
Gherson,

33

Credo che questo gergo di "callback" sia stato erroneamente usato in molti posti. La mia definizione sarebbe simile a:

Una funzione di richiamata è una funzione che si passa a qualcuno e si fa chiamare in un determinato momento.

Penso che la gente abbia appena letto la prima frase della definizione wiki:

un callback è un riferimento al codice eseguibile, o un pezzo di codice eseguibile, che viene passato come argomento ad altro codice.

Ho lavorato con molte API, vedi vari esempi negativi. Molte persone tendono a nominare un puntatore a funzione (un riferimento al codice eseguibile) o funzioni anonime (un pezzo di codice eseguibile) "callback", se sono solo funzioni perché hai bisogno di un altro nome per questo?

In realtà solo la seconda frase nella definizione della wiki rivela le differenze tra una funzione di callback e una normale:

Ciò consente a un livello software di livello inferiore di chiamare una subroutine (o funzione) definita in un livello di livello superiore.

quindi la differenza è chi passerai alla funzione e come verrà chiamata la tua funzione passata. Se si definisce semplicemente una funzione e la si passa a un'altra funzione e la si chiama direttamente nel corpo di tale funzione, non chiamarla callback. La definizione dice che la tua funzione passata verrà chiamata dalla funzione "di livello inferiore".

Spero che le persone possano smettere di usare questa parola in un contesto ambiguo, non può aiutare le persone a capire meglio solo peggio.


2
La tua risposta ha un senso ... ma ho difficoltà a immaginarla. Puoi fare un esempio?
CodyBugstein,

3
@Zane Wong :: Nell'ultimo hai scritto "La definizione dice che la tua funzione passata verrà chiamata dalla funzione" di livello inferiore "." Puoi spiegare cosa indica la funzione di livello inferiore? È meglio se fai un esempio.
Viku,

Un esempio sarebbe stato carino
Yousuf Azad,

1
Penso che la differenza tra la chiamata di funzione classica e lo stile di call-back sia legata alla direzione della dipendenza: se il modulo A dipende ("usa") il modulo B, A chiama una funzione di B, non è un callback. Se A passa un riferimento alla sua funzione a B, allora B chiama una funzione di A, questo è un callback: la chiamata va indietro rispetto alla dipendenza del modulo.
XouDo,

30

Manteniamolo semplice. Che cos'è una funzione di richiamata?

Esempio di parabola e analogia

Ho un segretario. Ogni giorno le chiedo di: (i) consegnare la posta in uscita della ditta all'ufficio postale, e dopo che lo ha fatto, per fare: (ii) qualunque compito le abbia scritto su una di quelle note appiccicose .

Ora, qual è il compito sulla nota adesiva? L'attività varia di giorno in giorno.

Supponiamo che in questo particolare giorno, le chieda di stampare alcuni documenti. Quindi lo scrivo sulla nota adesiva e la apposto sulla sua scrivania insieme alla posta in uscita che deve pubblicare.

In sintesi:

  1. in primo luogo, deve lasciare la posta e
  2. subito dopo , deve stampare alcuni documenti.

La funzione di richiamata è quella seconda attività: stampare quei documenti. Perché è fatto DOPO che la posta viene ritirata, e anche perché la nota adesiva che le dice di stampare il documento le viene data insieme alla posta che deve pubblicare.

Legiamolo ora al vocabolario di programmazione

  • Il nome del metodo in questo caso è: DropOffMail.
  • E la funzione di richiamata è: PrintOffDocuments. PrintOffDocuments è la funzione di richiamata perché vogliamo che il segretario lo faccia, solo dopo l'esecuzione di DropOffMail.
  • Quindi vorrei "passare: PrintOffDocuments come" argomento "al metodo DropOffMail. Questo è un punto importante.

Questo è tutto. Niente di più. Spero che sia stato chiarito per te - e in caso contrario, pubblica un commento e farò del mio meglio per chiarire.


18

Questo fa sembrare le richiamate come dichiarazioni di ritorno alla fine dei metodi.

Non sono sicuro che sia quello che sono.

Penso che i callback siano in realtà una chiamata a una funzione, come conseguenza dell'evocazione e del completamento di un'altra funzione.

Penso anche che i Callbacks siano pensati per rispondere all'invocazione originaria, in una sorta di "hey! Quella cosa che hai chiesto? L'ho fatto - pensavo solo di farti sapere - di nuovo a te".


1
+1 per l'interrogatorio di callbacks e dichiarazioni di ritorno. Sono stato sorpreso da questo e così anche molti laureati con cui lavoro.
8bitjunkie,

2
Buona risposta - mi ha aiutato a capirlo a differenza di molte altre risposte!
adaam,

18

Che cos'è il callback ?

  • In generale, viene effettuata una telefonata per restituire quella ricevuta da qualcuno.
  • Nell'informatica, un callback è un pezzo di codice eseguibile che viene passato come argomento ad altro codice. Quando la funzione ha finito con il suo lavoro (o quando si è verificato un evento), chiama la funzione di callback (ti richiama - da qui il nome).

Che cos'è una funzione di richiamata ?

  • una funzione di richiamata è come un Servo che "richiama" al suo Maestro quando ha completato un compito.
  • una funzione di callback è una funzione che viene passata a un'altra funzione (chiamiamo quest'altra funzione otherFunction) come parametro e la funzione di callback viene chiamata (o eseguita) all'interno di 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

In SOA, il callback consente ai moduli plug-in di accedere ai servizi dal contenitore / ambiente.

Analogia: richiamate. Asincrono. Esempio di vita reale non bloccante
per callback


Una funzione di callback non è essa stessa una funzione di ordine superiore. Viene passato a una funzione di ordine superiore.
danio

17

Call After sarebbe un nome migliore del nome stupido, callback . Quando o se la condizione viene soddisfatta all'interno di una funzione, chiama un'altra funzione, la funzione Chiama dopo , quella ricevuta come argomento.

Anziché codificare una funzione interna all'interno di una funzione, si scrive una funzione per accettare una funzione Call After già scritta come argomento. La chiamata Dopo potrebbe ottenere chiamato sulla base di cambiamenti di stato rilevato dal codice nella funzione che riceve l'argomento.


Questa è una grande idea. Ho cercato "chiamato sul retro" per cercare di spiegare questo. Ho potuto vedere qualcuno come Martin Fowler diffondere "call after" come un nuovo termine per questi sul suo blog fondamentale.
8bitjunkie,

15

Una funzione di callback è una funzione specificata per una funzione / metodo esistente, da invocare al completamento di un'azione, richiede un'ulteriore elaborazione, ecc.

In Javascript, o più specificamente jQuery, ad esempio, è possibile specificare un argomento di callback da chiamare al termine di un'animazione.

In PHP, la preg_replace_callback()funzione consente di fornire una funzione che verrà chiamata quando viene abbinata l'espressione regolare, passando le stringhe abbinate come argomenti.


10

guarda l'immagine :)Ecco come funziona

Il programma principale chiama la funzione di libreria (che potrebbe anche essere una funzione a livello di sistema) con il nome della funzione di callback. Questa funzione di callback potrebbe essere implementata in più modi. Il programma principale sceglie un callback secondo il requisito.

Infine, la funzione di libreria chiama la funzione di richiamata durante l'esecuzione.


7
Ti dispiacerebbe aggiungere anche una spiegazione testuale a questo? Se l'immagine svanisce, questa risposta perde tutto il contesto.
Tim Post

il testo di altre persone lo spiega meglio. l'unica cosa che mi è

Di tutte le descrizioni tortuose che ho visto qui, questa è quella che mi ha fatto andare "ahhhhh, ora ne vedo l'uso". Avere un voto.
DiBosco,

7

La semplice risposta a questa domanda è che una funzione di callback è una funzione chiamata tramite un puntatore a funzione. Se si passa il puntatore (indirizzo) di una funzione come argomento a un altro, quando quel puntatore viene utilizzato per chiamare la funzione a cui punta viene detto che viene effettuata una richiamata


7

Supponiamo di avere una funzione in sort(int *arraytobesorted,void (*algorithmchosen)(void))cui può accettare un puntatore a funzione come argomento che può essere utilizzato ad un certo punto sort()nell'implementazione. Quindi, qui il codice che viene indirizzato dal puntatore alla funzione algorithmchosenviene chiamato come funzione di callback .

E vedi il vantaggio è che possiamo scegliere qualsiasi algoritmo come:

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

Che, diciamo, sono stati implementati con il prototipo:

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

Questo è un concetto usato per raggiungere il polimorfismo nella programmazione orientata agli oggetti


Grande spiegazione su javascriptissexy.com/…; che ripubblicherò qui; Una funzione di callback è una funzione che viene passata a un'altra funzione come parametro e la funzione di callback viene chiamata o eseguita all'interno dell'altra funzione. // Nota che l'elemento nel parametro del metodo click è una funzione, non una variabile. // L'articolo è una funzione di callback $ ("# btn_1"). Click (function () {alert ("Btn 1 Clicked" );}); Come vedi nell'esempio precedente, passiamo una funzione come parametro al metodo click per eseguirla -
MarcoZen

4

“Nella programmazione per computer, un callback è un riferimento al codice eseguibile, o un pezzo di codice eseguibile, che viene passato come argomento ad altro codice. Ciò consente a un livello software di livello inferiore di chiamare una subroutine (o funzione) definita in un livello di livello superiore. " - Wikipedia

Richiamata in C usando il puntatore a funzione

In C, il callback viene implementato utilizzando il puntatore a funzione. Puntatore a funzione - come suggerisce il nome, è un puntatore a una funzione.

Ad esempio, int (* ptrFunc) ();

Qui, ptrFunc è un puntatore a una funzione che non accetta argomenti e restituisce un numero intero. NON dimenticare di inserire la parentesi, altrimenti il ​​compilatore supporrà che ptrFunc sia un normale nome di funzione, che non accetta nulla e restituisce un puntatore a un numero intero.

Ecco un po 'di codice per dimostrare il puntatore alla funzione.

#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;
}

Ora proviamo a capire il concetto di Callback in C usando il puntatore a funzione.

Il programma completo ha tre file: callback.c, reg_callback.h e 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)();                               
}

Se eseguiamo questo programma, l'output sarà

Questo è un programma che mostra la funzione di callback all'interno di register_callback all'interno di my_callback e torna all'interno del programma principale

La funzione di livello superiore chiama una funzione di livello inferiore come una normale chiamata e il meccanismo di richiamata consente alla funzione di livello inferiore di chiamare la funzione di livello superiore tramite un puntatore a una funzione di richiamata.

Richiamata in Java tramite l'interfaccia

Java non ha il concetto di puntatore a funzione Implementa il meccanismo di callback attraverso il suo meccanismo di interfaccia Qui invece di un puntatore a funzione, dichiariamo un'interfaccia con un metodo che verrà chiamato quando la chiamata termina il suo compito

Vorrei dimostrarlo con un esempio:

L'interfaccia di callback

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

Il chiamante o la classe di livello superiore

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
}
}

La funzione Chiamata o livello inferiore

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
}
}

Richiamata mediante il modello EventListener

  • Voce di elenco

Questo modello viene utilizzato per notificare da 0 a n numeri di osservatori / ascoltatori che una determinata attività è terminata

  • Voce di elenco

La differenza tra il meccanismo Callback e il meccanismo EventListener / Observer è che nel callback, il chiamante avvisa il singolo chiamante, mentre in Eventlisener / Observer, il chiamante può avvisare chiunque sia interessato a quell'evento (la notifica può andare ad alcune altre parti del applicazione che non ha attivato l'attività)

Lasciami spiegare con un esempio.

L'interfaccia dell'evento

public interface Events {

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

Widget di classe

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);
    }
}

Pulsante di classe

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

Casella di controllo della classe

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;
}
}

Classe di attività

pacchetto 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();
    }   
}

Altra classe

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...");
}
}

Classe principale

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);
}
}

Come puoi vedere dal codice sopra, che abbiamo un'interfaccia chiamata eventi che sostanzialmente elenca tutti gli eventi che possono accadere per la nostra applicazione. La classe Widget è la classe base per tutti i componenti dell'interfaccia utente come Button, Checkbox. Questi componenti dell'interfaccia utente sono gli oggetti che ricevono effettivamente gli eventi dal codice del framework. La classe Widget implementa l'interfaccia Eventi e inoltre ha due interfacce nidificate, vale a dire OnClickEventListener & OnLongClickEventListener

Queste due interfacce sono responsabili dell'ascolto di eventi che possono verificarsi sui componenti dell'interfaccia utente derivati ​​dal Widget come Button o Checkbox. Quindi, se confrontiamo questo esempio con il precedente esempio di Callback usando l'interfaccia Java, queste due interfacce funzionano come l'interfaccia di Callback. Quindi il codice di livello superiore (Here Activity) implementa queste due interfacce. E ogni volta che si verifica un evento su un widget, verrà chiamato il codice di livello superiore (o il metodo di queste interfacce implementato nel codice di livello superiore, che è qui Attività).

Ora lasciami discutere la differenza di base tra il modello Callback e Eventlistener. Come abbiamo detto che utilizzando Callback, Callee può notificare solo un singolo chiamante. Ma nel caso del modello EventListener, qualsiasi altra parte o classe dell'applicazione può registrarsi per gli eventi che possono verificarsi sul pulsante o sulla casella di controllo. L'esempio di questo tipo di classe è OtherClass. Se vedi il codice di OtherClass, scoprirai che si è registrato come listener di ClickEvent che può verificarsi nel pulsante definito nell'attività. La parte interessante è che, oltre all'attività (il chiamante), questa OtherClass verrà anche avvisata ogni volta che si verifica l'evento click sul pulsante.


Si prega di evitare solo le risposte dei collegamenti . Le risposte "a malapena più di un collegamento a un sito esterno" possono essere eliminate .
Quentin,

3

Una funzione di callback è una funzione che si passa (come riferimento o un puntatore) a una determinata funzione o oggetto. Questa funzione o oggetto richiamerà questa funzione in qualsiasi momento successivo, possibilmente più volte, per qualsiasi tipo di scopo:

  • notificando la fine di un'attività
  • richiedere il confronto tra due elementi (come in c qsort ())
  • riportare l'avanzamento di un processo
  • notifica di eventi
  • delegando l'installazione di un oggetto
  • delegare la pittura di un'area

...

Quindi descrivere un callback come una funzione chiamata alla fine di un'altra funzione o attività sta semplificando eccessivamente (anche se si tratta di un caso d'uso comune).


2

Un callback è un'idea di passare una funzione come parametro a un'altra funzione e farla richiamare una volta completato il processo.

Se ottieni il concetto di callback attraverso fantastiche risposte sopra, ti consiglio di imparare il background della sua idea.

"Cosa li ha spinti (informatici) a sviluppare callback?" Potresti imparare un problema che sta bloccando (specialmente bloccando l'interfaccia utente) E il callback non è l'unica soluzione ad esso. Ci sono molte altre soluzioni (es: Thread, Futures, Promises ...).


1

Un'area di utilizzo importante è quella di registrare una delle tue funzioni come handle (ovvero una callback) e quindi inviare un messaggio / chiamare una funzione per fare un lavoro o elaborarlo. Ora dopo che l'elaborazione è terminata, la funzione chiamata chiamerebbe la nostra funzione registrata (cioè ora la richiamata è terminata), indicando così che l'elaborazione è terminata.
Questo link di Wikipedia spiega abbastanza bene graficamente.


1

Una funzione di richiamata, nota anche come funzione di ordine superiore, è una funzione che viene passata a un'altra funzione come parametro e la funzione di richiamata viene chiamata (o eseguita) all'interno della funzione genitore.

$("#button_1").click(function() {
  alert("button 1 Clicked");
});

Qui abbiamo passato una funzione come parametro al metodo click. E il metodo click chiamerà (o eseguirà) la funzione di callback che le abbiamo passato.


2
Una funzione di callback non è essa stessa una funzione di ordine superiore. Viene passato a una funzione di ordine superiore.
danio

1

Funzione di richiamata Una funzione che è passata a un'altra funzione come argomento.

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

setTimeout(test_function, 2000);

Nota: nell'esempio sopra test_function utilizzato come argomento per la funzione setTimeout.


1
Benvenuto in Stack Overflow! Prima di rispondere a una domanda, leggi sempre le risposte esistenti. Questa risposta è già stata fornita. Invece di ripetere la risposta, vota la risposta esistente. Alcune linee guida per scrivere buone risposte possono essere trovate qui .
dferenc,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.