Comment expliquer les rappels en anglais simple? En quoi sont-ils différents d'appeler une fonction d'une autre fonction?

342

Comment expliquer les rappels en anglais simple? Comment sont-ils différents d'appeler une fonction d'une autre fonction en prenant un certain contexte de la fonction appelante? Comment expliquer leur puissance à un programmeur débutant?

Yahoo-Me
la source
1
Je crois que son nom scientifique est un style qui passe par la suite. Vous pouvez rechercher cela sur wiki.
ming_codes
1
Il y a quelques bonnes réponses à une question identique sur Quora aussi
DBR
La meilleure explication du rappel que j'ai jamais trouvée youtube.com/watch?v=xHneyv38Jro
Sameer Sinha

Réponses:

114

Souvent, une application doit exécuter différentes fonctions en fonction de son contexte / état. Pour cela, nous utilisons une variable dans laquelle nous stockons les informations sur la fonction à appeler. Selon son besoin, l'application définira cette variable avec les informations sur la fonction à appeler et appellera la fonction en utilisant la même variable.

En javascript, l'exemple est ci-dessous. Ici, nous utilisons l'argument de méthode comme variable où nous stockons des informations sur la fonction.

function processArray(arr, callback) {
    var resultArr = new Array(); 
    for (var i = arr.length-1; i >= 0; i--)
        resultArr[i] = callback(arr[i]);
    return resultArr;
}

var arr = [1, 2, 3, 4];
var arrReturned = processArray(arr, function(arg) {return arg * -1;});
// arrReturned would be [-1, -2, -3, -4]
Niraj Nawanit
la source
18
Bien qu'il s'agisse techniquement d'un rappel, l'explication donnée semble indistincte d'un pointeur de fonction générale. Il serait utile d'inclure une justification de la raison pour laquelle un rappel pourrait être utilisé.
Eric
4
Je ne comprends pas cette réponse. Peut-il s'agir davantage d'expliquer que le code?
Abhishek Singh
pourquoi ne pouvons-nous pas faire ce que nous faisons dans la fonction rappelée (la function(arg)) dans la processArray(arr,callback)fonction
Abhi
1
@JoSmo vous avez partiellement raison. Passez une variable + fonction de rappel en tant que paramètres en prenant le résultat créé avec la variable par la fonction d'origine et passez-le dans la fonction de rappel pour un traitement ultérieur. exemple: func1 (a, callback_func) {v = a + 1} et il existe une fonction de rappel prédéfinie: callback_func (v) {return v + 1;} cela augmentera a de 2, donc si vous passez l'argument de l'entier 4 dans "a" paramètre, callback_funct renverra 6 comme résultat. Lisez cette meilleure source de callbackhell.com que j'ai trouvée.
Dung
Cette réponse n'est pas claire. Pourrait être plus simple et articulé!
Arjun Kalidas
545

Je vais essayer de garder cette mort simple. Un "rappel" est une fonction qui est appelée par une autre fonction qui prend la première fonction comme paramètre. La plupart du temps, un "rappel" est une fonction qui est appelée lorsque quelque chose se produit. Ce quelque chose peut être appelé un "événement" en langage programmeur.

Imaginez ce scénario: vous attendez un colis dans quelques jours. Le forfait est un cadeau pour votre voisin. Par conséquent, une fois que vous avez reçu le colis, vous souhaitez qu'il soit apporté aux voisins. Vous n'êtes pas en ville et vous laissez donc des instructions à votre conjoint.

Vous pourriez leur dire de prendre le colis et de l'apporter aux voisins. Si votre conjoint était aussi stupide qu'un ordinateur, il s'asseyait à la porte et attendait le colis jusqu'à ce qu'il vienne (ne rien faire d'autre), puis une fois arrivé, il le rapportait aux voisins. Mais il y a une meilleure façon. Dites à votre conjoint qu'une fois qu'ils ont reçu le colis, ils doivent le rapporter aux voisins. Ensuite, ils peuvent reprendre leur vie normalement JUSQU'À ce qu'ils reçoivent le colis.

Dans notre exemple, la réception du colis est "l'événement" et son apport aux voisins est le "rappel". Votre conjoint "exécute" vos instructions pour apporter le colis uniquement lorsque le colis arrive. Bien mieux!

Ce genre de pensée est évident dans la vie quotidienne, mais les ordinateurs n'ont pas le même sens commun. Considérez comment les programmeurs écrivent normalement dans un fichier:

fileObject = open(file)
# now that we have WAITED for the file to open, we can write to it
fileObject.write("We are writing to the file.")
# now we can continue doing the other, totally unrelated things our program does

Ici, nous ATTENDONS que le fichier s'ouvre, avant de lui écrire. Cela "bloque" le flux d'exécution, et notre programme ne peut faire aucune des autres choses dont il pourrait avoir besoin! Et si nous pouvions le faire à la place:

# we pass writeToFile (A CALLBACK FUNCTION!) to the open function
fileObject = open(file, writeToFile)
# execution continues flowing -- we don't wait for the file to be opened
# ONCE the file is opened we write to it, but while we wait WE CAN DO OTHER THINGS!

Il s'avère que nous le faisons avec certains langages et frameworks. C'est vraiment cool! Consultez Node.js pour vous familiariser avec ce type de réflexion.

Josh Imhoff
la source
6
Ceci est correct, mais ne couvre pas tous les cas d'utilisation courants pour les rappels. Souvent, vous utilisez des rappels lorsque vous devez appeler une fonction avec des arguments qui seraient traités dans le processus d'une autre fonction. Par exemple, en PHP array_filter () et array_map () prennent les rappels à appeler dans une boucle.
Haralan Dobrev
2
L'exemple de fichier d'écriture est-il approprié? Il semble faire des hypothèses sur le openfonctionnement. Il est plausible que cela openpuisse bloquer en interne en attendant que le système d'exploitation fasse sa magie noire, sur laquelle le rappel est exécuté. Il n'y a aucune différence de résultat dans un tel cas.
Kenneth K.
23
Belle explication, mais je suis un peu déroutant. Le rappel est-il multithread?
Premraj
1
Excellent exemple! Je cherchais un anglais simple partout et c'est le premier que j'ai trouvé jusqu'à présent :)
ChristoKiwi
1
Qu'est-ce qui rend la fonction ouverte dans votre exemple non bloquante? ouvert peut encore bloquer le flux de l'exécution ..
Koray Tugay
82

Comment expliquer les rappels en anglais simple?

En clair, une fonction de rappel est comme un travailleur qui "rappelle" à son responsable lorsqu'il a terminé une tâche .

Comment sont-ils différents d'appeler une fonction d'une autre fonction en prenant un certain contexte de la fonction appelante?

Il est vrai que vous appelez une fonction à partir d'une autre fonction, mais la clé est que le rappel est traité comme un objet, vous pouvez donc changer la fonction à appeler en fonction de l'état du système (comme le modèle de conception de stratégie).

Comment expliquer leur puissance à un programmeur débutant?

La puissance des rappels est facilement visible sur les sites Web de style AJAX qui doivent extraire des données d'un serveur. Le téléchargement des nouvelles données peut prendre un certain temps. Sans rappels, l'intégralité de votre interface utilisateur "se bloquerait" lors du téléchargement des nouvelles données, ou vous auriez besoin d'actualiser la page entière plutôt qu'une partie seulement. Avec un rappel, vous pouvez insérer une image "en cours de chargement" et la remplacer par les nouvelles données une fois qu'elle est chargée.

Du code sans rappel:

function grabAndFreeze() {
    showNowLoading(true);
    var jsondata = getData('http://yourserver.com/data/messages.json');
    /* User Interface 'freezes' while getting data */
    processData(jsondata);
    showNowLoading(false);
    do_other_stuff(); // not called until data fully downloaded
}

function processData(jsondata) { // do something with the data
   var count = jsondata.results ? jsondata.results.length : 0;
   $('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
   $('#results_messages').html(jsondata.results || '(no new messages)');
}

Avec rappel:

Voici un exemple avec un rappel, en utilisant getJSON de jQuery :

function processDataCB(jsondata) { // callback: update UI with results
   showNowLoading(false);
   var count = jsondata.results ? jsondata.results.length : 0;
   $('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
   $('#results_messages').html(jsondata.results || '(no new messages)');
}

function grabAndGo() { // and don't freeze
    showNowLoading(true);
    $('#results_messages').html(now_loading_image);
    $.getJSON("http://yourserver.com/data/messages.json", processDataCB);
    /* Call processDataCB when data is downloaded, no frozen User Interface! */
    do_other_stuff(); // called immediately
}

Avec fermeture:

Souvent, le rappel doit accéder à statepartir de la fonction appelante à l'aide de a closure, ce qui revient à dire que le travailleur doit obtenir des informations du gestionnaire avant de pouvoir terminer sa tâche . Pour créer le closure, vous pouvez incorporer la fonction afin qu'elle voit les données dans le contexte d'appel:

/* Grab messages, chat users, etc by changing dtable. Run callback cb when done.*/
function grab(dtable, cb) { 
    if (null == dtable) { dtable = "messages"; }
    var uiElem = "_" + dtable;
    showNowLoading(true, dtable);
    $('#results' + uiElem).html(now_loading_image);
    $.getJSON("http://yourserver.com/user/"+dtable+".json", cb || function (jsondata) {
       // Using a closure: can "see" dtable argument and uiElem variables above.
       var count = jsondata.results ? jsondata.results.length : 0, 
           counterMsg = ['Fetched', count, 'new', dtable].join(' '),
           // no new chatters/messages/etc
           defaultResultsMsg = ['(no new ', dtable, ')'].join(''); 
       showNowLoading(false, dtable);
       $('#counter' + uiElem).text(counterMsg);
       $('#results'+ uiElem).html(jsondata.results || defaultResultsMsg);
    });
    /* User Interface calls cb when data is downloaded */

    do_other_stuff(); // called immediately
}

Usage:

// update results_chatters when chatters.json data is downloaded:
grab("chatters"); 
// update results_messages when messages.json data is downloaded
grab("messages"); 
// call myCallback(jsondata) when "history.json" data is loaded:
grab("history", myCallback); 

Fermeture

Enfin, voici une définition closurede Douglas Crockford :

Les fonctions peuvent être définies à l'intérieur d'autres fonctions. La fonction interne a accès aux variables et paramètres de la fonction externe. Si une référence à une fonction interne survit (par exemple, en tant que fonction de rappel), les variables de la fonction externe survivent également.

Voir également:

user508994
la source
12
+1. Le premier paragraphe est un coup sur l'argent . Cependant, le reste va assez rapidement dans le jargon informatique.
TarkaDaal
41

Je suis stupéfait de voir tant de gens intelligents ne pas insister sur la réalité que le mot "rappel" est devenu utilisé de deux manières incohérentes.

Les deux méthodes impliquent la personnalisation d'une fonction en passant des fonctionnalités supplémentaires (une définition de fonction, anonyme ou nommée) à une fonction existante. c'est à dire.

customizableFunc(customFunctionality)

Si la fonctionnalité personnalisée est simplement connectée au bloc de code, vous avez personnalisé la fonction, comme ça.

    customizableFucn(customFunctionality) {
      var data = doSomthing();
      customFunctionality(data);
      ...
    }

Bien que ce type de fonctionnalité injectée soit souvent appelé "rappel", il n'y a rien de contingent à ce sujet. Un exemple très évident est la méthode forEach dans laquelle une fonction personnalisée est fournie comme argument à appliquer à chaque élément d'un tableau pour modifier le tableau.

Mais ceci est fondamentalement distinct de l'utilisation des fonctions de "rappel" pour la programmation asynchrone , comme dans AJAX ou node.js ou simplement dans l'attribution de fonctionnalités aux événements d'interaction utilisateur (comme les clics de souris). Dans ce cas, l'idée est d'attendre qu'un événement contingent se produise avant d'exécuter la fonctionnalité personnalisée. Cela est évident dans le cas de l'interaction avec l'utilisateur, mais est également important dans les processus d'E / S (entrée / sortie) qui peuvent prendre du temps, comme la lecture de fichiers à partir du disque. C'est là que le terme "rappel" prend tout son sens. Une fois qu'un processus d'E / S est démarré (comme demander un fichier à lire à partir du disque ou un serveur pour renvoyer les données d'une requête http) un asynchronele programme n'attend pas qu'il se termine. Il peut poursuivre les tâches planifiées ensuite et ne répondre avec la fonctionnalité personnalisée qu'après avoir été informé que le fichier lu ou la demande http est terminé (ou qu'il a échoué) et que les données sont disponibles pour la fonctionnalité personnalisée. C'est comme appeler une entreprise au téléphone et laisser votre numéro de "rappel", afin qu'ils puissent vous appeler quand quelqu'un est disponible pour vous recontacter. C'est mieux que de rester en ligne pour qui sait combien de temps et ne pas pouvoir s'occuper d'autres affaires.

L'utilisation asynchrone implique intrinsèquement certains moyens d'écouter l'événement souhaité (par exemple, l'achèvement du processus d'E / S) de sorte que, lorsqu'il se produit (et uniquement lorsqu'il se produit), la fonctionnalité de "rappel" personnalisée est exécutée. Dans l'exemple AJAX évident, lorsque les données arrivent réellement du serveur, la fonction "rappel" est déclenchée pour utiliser ces données pour modifier le DOM et donc redessiner la fenêtre du navigateur dans cette mesure.

Récapituler. Certaines personnes utilisent le mot «rappel» pour faire référence à tout type de fonctionnalité personnalisée qui peut être injectée dans une fonction existante comme argument. Mais, du moins pour moi, l'utilisation la plus appropriée du mot est celle où la fonction de "rappel" injectée est utilisée de manière asynchrone - pour être exécutée uniquement lors de la survenance d'un événement dont elle attend la notification.

Robert Polevoi
la source
Ainsi, lorsque la fonction rappelle, où revient le processus? Par exemple, s'il y a quatre lignes de code; 1.fileObject = open (fichier, writeToFile); 2. doSomething1 (); 3. doSomething2 (); 4. doSomething3 ().
MagicLAMP
La ligne 1 est exécutée, mais au lieu d'attendre l'ouverture du fichier, passe à la ligne 2, puis 3. À ce stade, le fichier s'ouvre et (une fois que la ligne 3 a terminé toute opération de sémaphore) rappelle au compteur de programme pour dire " passer le contrôle à writeToFile "qui fait des trucs, et quand il est terminé passe le contrôle au point où l'INT s'est produit à la ligne 3, ou à la ligne 4 si la ligne 3 devait se terminer.
MagicLAMP
1
Ceci est une explication très articulée d'un autre point important: par exemple la différence entre la fonction transmise en tant qu'argument Array.prototype.forEach()et la fonction transmise en tant qu'argument setTimeout(), et ce sont des chevaux de couleurs différentes en ce qui concerne la façon dont vous raisonnez à propos de votre programme. .
mikermcneil
26

En termes non programmeurs, un rappel est un remplissage à blanc dans un programme.

Un élément commun sur de nombreux formulaires papier est «Personne à appeler en cas d'urgence». Il y a une ligne vierge ici. Vous écrivez le nom et le numéro de téléphone de quelqu'un. En cas d'urgence, cette personne est appelée.

  • Tout le monde reçoit le même formulaire vierge, mais
  • Tout le monde peut écrire un numéro de contact d'urgence différent.

C'est la clé. Vous ne modifiez pas le formulaire (le code, généralement celui de quelqu'un d'autre). Cependant, vous pouvez remplir les informations manquantes ( votre numéro).

Exemple 1:

Les rappels sont utilisés comme méthodes personnalisées, éventuellement pour ajouter / modifier le comportement d'un programme. Par exemple, prenez du code C qui exécute une fonction, mais ne sait pas comment imprimer la sortie. Tout ce qu'il peut faire, c'est créer une chaîne. Lorsqu'il essaie de savoir quoi faire avec la chaîne, il voit une ligne vierge. Mais, le programmeur vous a donné le blanc pour écrire votre rappel!

Dans cet exemple, vous n'utilisez pas de crayon pour remplir un blanc sur une feuille de papier, vous utilisez la fonction set_print_callback(the_callback).

  • La variable vide dans le module / code est la ligne vierge,
  • set_print_callback est le crayon,
  • et ce the_callbacksont vos informations que vous remplissez.

Vous avez maintenant rempli cette ligne vierge dans le programme. Chaque fois qu'il a besoin d'imprimer la sortie, il regardera cette ligne vierge et suivra les instructions là-bas (c'est-à-dire appeler la fonction que vous y mettez.) Pratiquement, cela permet la possibilité d'imprimer à l'écran, dans un fichier journal, sur une imprimante, via une connexion réseau, ou toute combinaison de ceux-ci. Vous avez rempli le blanc avec ce que vous voulez faire.

Exemple 2:

Quand on vous dit que vous devez appeler un numéro d'urgence, vous allez lire ce qui est écrit sur le formulaire papier, puis appelez le numéro que vous lisez. Si cette ligne est vide, rien ne sera fait.

La programmation Gui fonctionne de la même manière. Lorsqu'un bouton est cliqué, le programme doit déterminer ce qu'il faut faire ensuite. Il va et cherche le rappel. Ce rappel se trouve dans un espace vierge intitulé "Voici ce que vous faites lorsque vous cliquez sur Button1"

La plupart des IDE remplissent automatiquement le blanc pour vous (écrivez la méthode de base) lorsque vous le lui demandez (par exemple button1_clicked). Cependant, ce blanc peut avoir n'importe quelle méthode que vous sachez bien s'il vous plaît . Vous pouvez appeler la méthode run_computationsou butter_the_biscuitstant que vous mettez le nom de ce rappel dans le blanc approprié. Vous pouvez mettre "555-555-1212" dans le numéro d'urgence. Cela n'a pas beaucoup de sens, mais c'est permis.


Remarque finale: Cette ligne vierge que vous remplissez avec le rappel? Il peut être effacé et réécrit à volonté. (si vous devez ou non est une autre question, mais cela fait partie de leur pouvoir)

JoeyG
la source
22

Il vaut toujours mieux commencer par un exemple :).

Supposons que vous ayez deux modules A et B.

Vous voulez que le module A soit averti lorsqu'un événement / une condition se produit dans le module B. Cependant, le module B n'a aucune idée de votre module A. Tout ce qu'il sait, c'est une adresse vers une fonction particulière (du module A) via un pointeur de fonction qui est fourni par le module A.

Donc, tout ce que B doit faire maintenant, c'est un "rappel" dans le module A quand un événement / une condition particulière se produit en utilisant le pointeur de fonction. A peut effectuer un traitement supplémentaire à l'intérieur de la fonction de rappel.

*) Un avantage clair ici est que vous résumez tout sur le module A du module B. Le module B n'a pas à se soucier de savoir qui / quoi est le module A.

Gargi Srinivas
la source
Donc, les paramètres de la fonction dans A sont fournis dans le module B, est-ce correct?
U.Savas
21

Imaginez que vous ayez besoin d'une fonction qui renvoie 10 au carré pour que vous écriviez une fonction:

function tenSquared() {return 10*10;}

Plus tard, vous aurez besoin de 9 au carré pour écrire une autre fonction:

function nineSquared() {return 9*9;}

Finalement, vous remplacerez tous ces éléments par une fonction générique:

function square(x) {return x*x;}

La même réflexion s'applique pour les rappels. Vous avez une fonction qui fait quelque chose et quand vous avez terminé, appelez doA:

function computeA(){
    ...
    doA(result);
}

Plus tard, vous souhaitez que la même fonction exacte appelle doB à la place, vous pouvez dupliquer la fonction entière:

function computeB(){
    ...
    doB(result);
}

Ou vous pouvez passer une fonction de rappel en tant que variable et ne devez avoir la fonction qu'une seule fois:

function compute(callback){
    ...
    callback(result);
}

Il suffit ensuite d'appeler compute (doA) et compute (doB).

Au-delà de la simplification du code, il laisse le code asynchrone vous faire savoir qu'il s'est terminé en appelant votre fonction arbitraire à la fin, comme lorsque vous appelez quelqu'un au téléphone et laissez un numéro de rappel.

Brian Nickel
la source
Vous passez donc la fonction comme paramètre. Est-ce que tout langage de programmation permet de passer la fonction en paramètre? Si non, alors pouvez-vous montrer un exemple sur la façon dont vous implémentez la fonction de rappel sur ces langues.
Quazi Irfan
21

Johny le programmeur a besoin d'une agrafeuse, alors il descend au service des fournitures de bureau et en demande une, après avoir rempli le formulaire de demande, il peut soit rester là et attendre que le commis va chercher l'agrafeuse dans l'entrepôt (comme un appel de fonction de blocage) ) ou allez faire autre chose en attendant.

comme cela prend généralement du temps, johny met une note avec le formulaire de demande leur demandant de l'appeler lorsque l'agrafeuse est prête à être ramassée, alors en attendant, il peut aller faire autre chose comme faire une sieste sur son bureau.

tovmeod
la source
1
Cela semble un peu plus proche des promesses que des rappels: blog.jcoglan.com/2013/03/30/…
Thomas
2
Les promesses ne sont que du sucre syntaxique autour des rappels.
Deven Phillips
11

Vous vous sentez mal alors vous allez chez le médecin. Il vous examine et détermine que vous avez besoin de médicaments. Il prescrit certains médicaments et appelle l'ordonnance dans votre pharmacie locale. Tu rentres chez toi. Plus tard, votre pharmacie vous appelle pour vous informer que votre ordonnance est prête. Vous allez le chercher.

effigie
la source
Très bonne analogie. Pourriez-vous développer un peu plus, peut-être avec quelques exemples (simples) liés à la programmation?
a20
10

Il y a deux points à expliquer, l'un est comment fonctionne un rappel (en faisant circuler une fonction qui peut être appelée sans aucune connaissance de son contexte), l'autre à quoi il sert (gérer les événements de manière asynchrone).

L'analogie de l'attente d'un colis qui a été utilisé par d'autres réponses est bonne pour expliquer les deux. Dans un programme informatique, vous diriez à l'ordinateur d'attendre un colis. Habituellement, il resterait là et attendrait (et ne ferait rien d'autre) jusqu'à ce que le colis arrive, peut-être indéfiniment s'il n'arrive jamais. Pour les humains, cela semble idiot, mais sans autres mesures, cela est totalement naturel pour un ordinateur.

Maintenant, le rappel serait la cloche à votre porte d'entrée. Vous fournissez au service de colis un moyen de vous informer de l'arrivée du colis sans qu'ils aient à savoir où (même si) vous êtes dans la maison, ni comment fonctionne la cloche. (Par exemple, certaines "cloches" envoient en fait un appel téléphonique.) Parce que vous avez fourni une "fonction de rappel" qui peut être "appelée" à tout moment, hors contexte, vous pouvez maintenant arrêter de vous asseoir sur le porche avant et "gérer la événement "(d'arrivée de colis) chaque fois qu'il est temps.

Hanno Fietz
la source
C'est un anglais simple.
Jeb50
Cela semble être la meilleure explication!
Vishal Sharma
6

Imaginez qu'un ami quitte votre maison et vous lui dites: «Appelez-moi quand vous rentrez pour que je sache que vous êtes arrivé en toute sécurité»; c'est (littéralement) un rappel . C'est ce qu'est une fonction de rappel, quelle que soit la langue. Vous voulez qu'une procédure vous revienne le contrôle lorsqu'elle a terminé une tâche, vous lui donnez donc une fonction à utiliser pour vous rappeler.

En Python, par exemple,

grabDBValue( (lambda x: passValueToGUIWindow(x) ))

grabDBValuepourrait être écrit pour extraire uniquement une valeur d'une base de données, puis vous laisser spécifier quoi faire réellement avec la valeur, afin qu'il accepte une fonction. Vous ne savez pas quand ou si vous grabDBValuereviendrez, mais si / quand il le fait, vous savez ce que vous voulez qu'il fasse. Ici, je passe une fonction anonyme (ou lambda ) qui envoie la valeur à une fenêtre GUI. Je pourrais facilement changer le comportement du programme en faisant ceci:

grabDBValue( (lambda x: passToLogger(x) ))

Les rappels fonctionnent bien dans les langages où les fonctions sont des valeurs de première classe , tout comme les entiers habituels, les chaînes de caractères, les booléens, etc. En C, vous pouvez "passer" une fonction en lui passant un pointeur et l'appelant peut l'utiliser; en Java, l'appelant demandera une classe statique d'un certain type avec un certain nom de méthode car il n'y a pas de fonctions ("méthodes", en fait) en dehors des classes; et dans la plupart des autres langages dynamiques, vous pouvez simplement passer une fonction avec une syntaxe simple.

Protip:

Dans les langues à portée lexicale (comme Scheme ou Perl), vous pouvez tirer une astuce comme celle-ci:

my $var = 2;
my $val = someCallerBackFunction(sub callback { return $var * 3; });
# Perlistas note: I know the sub doesn't need a name, this is for illustration

$valdans ce cas, ce sera 6parce que le rappel a accès aux variables déclarées dans l' environnement lexical où il a été défini. La portée lexicale et les rappels anonymes sont une combinaison puissante qui mérite une étude plus approfondie pour le programmeur débutant.

gatlin
la source
1
+1. En fait, j'aime bien cette réponse. L'explication de ce qu'est un rappel est , est simple et concis.
TarkaDaal
6

Vous avez du code que vous souhaitez exécuter. Normalement, lorsque vous l'appelez, vous attendez qu'il soit terminé avant de continuer (ce qui peut faire griser votre application / produire un temps de rotation pour un curseur).

Une autre méthode consiste à exécuter ce code en parallèle et à poursuivre votre propre travail. Mais que se passe-t-il si votre code d'origine doit faire des choses différentes selon la réponse du code qu'il a appelé? Eh bien, dans ce cas, vous pouvez transmettre le nom / l'emplacement du code que vous souhaitez qu'il appelle quand c'est fait. Il s'agit d'un "rappel".

Code normal: Demander des informations-> Informations sur le processus-> Traiter les résultats du traitement-> Continuer à faire d'autres choses.

Avec les rappels: Demandez des informations-> Informations sur le processus-> Continuez à faire d'autres choses. Et à un moment ultérieur -> Traitez les résultats du traitement.

Andrew Ducker
la source
6

Sans rappel ni autres ressources de programmation spéciales (comme le filetage, etc.), un programme est exactement une séquence d'instructions qui sont exécutées séquentiellement les unes après les autres , et même avec une sorte de "comportement dynamique" déterminé par certaines conditions, tous les scénarios possibles doit être préalablement programmé .

Donc, si nous devons fournir un véritable comportement dynamique à un programme, nous pouvons utiliser le rappel. Avec le rappel, vous pouvez indiquer par paramètres, un programme pour appeler un autre programme fournissant certains paramètres précédemment définis et peut attendre certains résultats ( c'est le contrat ou la signature d'opération ), de sorte que ces résultats peuvent être produits / traités par un programme tiers qui n'était pas pas connu auparavant.

Cette technique est le fondement du polymorphisme appliqué aux programmes, fonctions, objets et à toutes les autres unités de code exécutées par les ordinateurs.

Le monde humain utilisé comme exemple de rappel est bien expliqué lorsque vous faites un travail, supposons que vous êtes un peintre ( ici vous êtes le programme principal, qui peint ) et appelez parfois votre client pour lui demander d'approuver le résultat de votre travail , donc, il décide si l'image est bonne ( votre client est le programme tiers ).

Dans l'exemple ci-dessus, vous êtes un peintre et "déléguez" à d'autres le travail d'approuver le résultat, l'image est le paramètre et chaque nouveau client (la "fonction" rappelée) change le résultat de votre travail en décidant ce qu'il veut sur l'image ( la décision prise par les clients est le résultat renvoyé de la "fonction de rappel" ).

J'espère que cette explication pourra être utile.

Luciano
la source
6

Imaginons que vous me confiez une tâche potentiellement longue: obtenir les noms des cinq premières personnes uniques que vous rencontrez. Cela peut prendre des jours si je suis dans une zone peu peuplée. Vous n'êtes pas vraiment intéressé à vous asseoir sur vos mains pendant que je cours, alors vous dites: "Lorsque vous avez la liste, appelez-moi sur mon portable et relisez-la-moi. Voici le numéro.".

Vous m'avez donné une référence de rappel - une fonction que je suis censé exécuter afin de transférer le traitement ultérieur.

En JavaScript, cela pourrait ressembler à ceci:

var lottoNumbers = [];
var callback = function(theNames) {
  for (var i=0; i<theNames.length; i++) {
    lottoNumbers.push(theNames[i].length);
  }
};

db.executeQuery("SELECT name " +
                "FROM tblEveryOneInTheWholeWorld " +
                "ORDER BY proximity DESC " +
                "LIMIT 5", callback);

while (lottoNumbers.length < 5) {
  playGolf();
}
playLotto(lottoNumbers);

Cela pourrait probablement être amélioré de nombreuses façons. Par exemple, vous pouvez fournir un deuxième rappel: si cela prend plus d'une heure, appelez le téléphone rouge et dites à la personne qui répond que vous avez expiré.

steamer25
la source
6

Les rappels sont plus facilement décrits en termes de système téléphonique. Un appel de fonction est analogue à appeler une personne au téléphone, à lui poser une question, à obtenir une réponse et à raccrocher; l'ajout d'un rappel modifie l'analogie de sorte qu'après lui avoir posé une question, vous lui donnez également votre nom et votre numéro afin qu'elle puisse vous rappeler avec la réponse. - Paul Jakubik, "Implémentations de rappel en C ++"

DejanLekic
la source
Une explication plus simple serait: j'appelle quelqu'un, elle est en réunion, je laisse un numéro de téléphone, elle rappelle.
Lonely
5

Un rappel est une fonction qui sera appelée par une deuxième fonction. Cette deuxième fonction ne sait pas à l'avance quelle fonction elle appellera. Ainsi, l' identité de la fonction de rappel est stockée quelque part, ou transmise à la deuxième fonction en tant que paramètre. Cette «identité», selon le langage de programmation, peut être l'adresse du rappel, ou une autre sorte de pointeur, ou ce peut être le nom de la fonction. Le principe est le même, nous stockons ou transmettons des informations qui identifient sans ambiguïté la fonction.

Le moment venu, la deuxième fonction peut appeler le rappel, en fournissant des paramètres en fonction des circonstances à ce moment. Il peut même choisir le rappel parmi un ensemble de rappels possibles. Le langage de programmation doit fournir une sorte de syntaxe pour permettre à la deuxième fonction d'appeler le rappel, connaissant son «identité».

Ce mécanisme a de nombreuses utilisations possibles. Avec les rappels, le concepteur d'une fonction peut la personnaliser en lui faisant appeler tous les rappels fournis. Par exemple, une fonction de tri peut prendre un rappel comme paramètre, et ce rappel peut être une fonction de comparaison de deux éléments pour décider lequel vient en premier.

Soit dit en passant, selon le langage de programmation, le mot "fonction" dans la discussion ci-dessus peut être remplacé par "bloc", "fermeture", "lambda", etc.

David Casseres
la source
5

Habituellement, nous envoyions des variables aux fonctions. Supposons que vous ayez une tâche où la variable doit être traitée avant d'être donnée comme argument - vous pouvez utiliser le rappel.

function1(var1, var2) est la manière habituelle.

Que faire si je souhaite var2être traité puis envoyé en argument? function1(var1, function2(var2))

Il s'agit d'un type de rappel - où function2exécute du code et renvoie une variable à la fonction initiale.

Nishant
la source
2
Qu'est-ce qu'un autre type de rappel?
johnny
@johnny: Il existe des rappels de navigateur normaux qui se déclenchent lorsqu'un Ajax est terminé, etc.
Nishant
4

Une explication métaphorique:

J'ai un colis que je veux livrer à un ami et je veux aussi savoir quand mon ami le recevra.

Je prends donc le colis au bureau de poste et je leur demande de le livrer. Si je veux savoir quand mon ami reçoit le colis, j'ai deux options:

(a) Je peux attendre au bureau de poste jusqu'à ce qu'il soit livré.

(b) Je recevrai un e-mail lors de sa livraison.

L'option (b) est analogue à un rappel.

tonylo
la source
4

Pour enseigner les rappels, vous devez d'abord enseigner le pointeur. Une fois que les élèves auront compris l'idée de pointer vers une variable, l'idée des rappels deviendra plus facile. En supposant que vous utilisez C / C ++, ces étapes peuvent être suivies.

  • Montrez d'abord à vos élèves comment utiliser et manipuler des variables à l'aide de pointeurs en plus d'utiliser les identificateurs de variable normaux.
  • Ensuite, apprenez-leur qu'il y a des choses qui ne peuvent être faites qu'avec des pointeurs (comme passer une variable par référence).
  • Dites-leur ensuite comment le code ou les fonctions exécutables sont comme certaines autres données (ou variables) dans la mémoire. Ainsi, les fonctions ont également des adresses ou des pointeurs.
  • Ensuite, montrez-leur comment les fonctions peuvent être appelées avec des pointeurs de fonction et dites-leur que ce sont des rappels.
  • Maintenant, la question est, pourquoi tous ces tracas pour appeler certaines fonctions? Quel est l'avantage? Comme les pointeurs de données, le pointeur de fonction, également appelé rappel, présente certains avantages par rapport à l'utilisation d'identificateurs normaux.
  • Le premier est que les identifiants de fonction ou les noms de fonction ne peuvent pas être utilisés comme données normales. Je veux dire, vous ne pouvez pas créer une structure de données avec des fonctions (comme un tableau ou une liste liée de fonctions). Mais avec les rappels, vous pouvez créer un tableau, une liste chaînée ou les utiliser avec d'autres données comme dans un dictionnaire de paires clé-valeur ou d'arbres, ou toute autre chose. C'est un puissant avantage. Et d'autres avantages sont en fait des enfants de celui-ci.
  • L'utilisation la plus courante des rappels est observée dans la programmation des pilotes d'événements. Où une ou plusieurs fonctions sont exécutées sur la base d'un signal entrant. Avec les rappels, un dictionnaire peut être maintenu pour mapper les signaux avec les rappels. La résolution du signal d'entrée et l'exécution du code correspondant deviennent alors beaucoup plus faciles.
  • La deuxième utilisation des rappels qui me vient à l'esprit est les fonctions d'ordre supérieur. Les fonctions qui prennent d'autres fonctions comme arguments d'entrée. Et pour envoyer des fonctions comme arguments, nous avons besoin de rappels. Un exemple peut être une fonction qui prend un tableau et un rappel. Il effectue ensuite le rappel sur chacun des éléments du tableau et renvoie les résultats dans un autre tableau. Si nous transmettons à la fonction un rappel doublant, nous obtenons un tableau à valeur doublée. Si nous réussissons un rappel au carré, nous obtenons des carrés. Pour les racines carrées, envoyez simplement un rappel approprié. Cela ne peut pas être fait avec des fonctions normales.

Il pourrait y avoir beaucoup plus de choses. Impliquez les étudiants et ils découvriront. J'espère que cela t'aides.

Gulshan
la source
1
Ma autre réponse liée à ce sujet dans programmers.SE programmers.stackexchange.com/a/75449/963
Gulshan
3

En clair, un rappel est une promesse. Joe, Jane, David et Samantha partagent un covoiturage pour travailler. Joe conduit aujourd'hui. Jane, David et Samantha ont deux options:

  1. Vérifiez la fenêtre toutes les 5 minutes pour voir si Joe est absent
  2. Continuez à faire leur travail jusqu'à ce que Joe sonne.

Option 1: Cela ressemble plus à un exemple d'interrogation où Jane serait coincée dans une "boucle" vérifiant si Joe est à l'extérieur. Jane ne peut rien faire d'autre en attendant.

Option 2: il s'agit de l'exemple de rappel. Jane dit à Joe de sonner à sa porte quand il est dehors. Elle lui donne une "fonction" pour sonner à la porte. Joe n'a pas besoin de savoir comment fonctionne la sonnette de porte ni où elle se trouve, il lui suffit d'appeler cette fonction, c'est-à-dire de sonner la sonnette de porte quand il est là.

Les rappels sont déterminés par des «événements». Dans cet exemple, «l'événement» est l'arrivée de Joe. Dans Ajax, par exemple, les événements peuvent être "succès" ou "échec" de la demande asynchrone et chacun peut avoir des rappels identiques ou différents.

En termes d'applications JavaScript et de rappels. Nous devons également comprendre les «fermetures» et le contexte d'application. À quoi «cela» fait référence peut facilement confondre les développeurs JavaScript. Dans cet exemple, dans la méthode / le rappel "ring_the_door_bell ()" de chaque personne, il peut y avoir d'autres méthodes que chaque personne doit appliquer en fonction de sa routine matinale, par exemple. "éteins la télévision()". Nous voudrions que "ceci" fasse référence à l'objet "Jane" ou à l'objet "David" afin que chacun puisse configurer tout ce dont il a besoin avant que Joe ne les récupère. C'est là que la configuration du rappel avec Joe nécessite de parodier la méthode afin que "ceci" se réfère au bon objet.

J'espère que cela pourra aider!

Nael El Shawwa
la source
3

Un rappel est une enveloppe pré-adressée et affranchie. Lorsque vous appelez une fonction, c'est comme envoyer une lettre. Si vous souhaitez que cette fonction appelle une autre fonction, vous fournissez ces informations sous la forme d'une référence ou d'une adresse.

pete
la source
3

Je pense que c'est une tâche assez facile à expliquer.

Au premier rappel, ce ne sont que des fonctions ordinaires.
Et le plus est que nous appelons cette fonction (appelons-la A) de l'intérieur d'une autre fonction (appelons-la B).

La magie à ce sujet est que je décide quelle fonction doit être appelée par la fonction depuis l' extérieur de B.

Au moment où j'écris la fonction BI, je ne sais pas quelle fonction de rappel doit être appelée. Au moment où j'appelle la fonction BI, je dis aussi à cette fonction d'appeler la fonction A. C'est tout.

yunzen
la source
3

Qu'est-ce qu'une fonction de rappel?

La réponse simple à cette première question est qu'une fonction de rappel est une fonction qui est appelée via un pointeur de fonction. Si vous passez le pointeur (adresse) d'une fonction comme argument à un autre, lorsque ce pointeur est utilisé pour appeler la fonction vers laquelle il pointe, il est dit qu'un rappel est effectué.

La fonction de rappel est difficile à tracer, mais parfois elle est très utile. Surtout lorsque vous concevez des bibliothèques. La fonction de rappel est comme demander à votre utilisateur de vous donner un nom de fonction, et vous appellerez cette fonction sous certaines conditions.

Par exemple, vous écrivez une minuterie de rappel. Il vous permet de spécifier la durée et la fonction à appeler, et la fonction sera rappelée en conséquence. "Exécutez myfunction () toutes les 10 secondes pendant 5 fois"

Ou vous pouvez créer un répertoire de fonctions, en passant une liste de noms de fonctions et demander à la bibliothèque de rappeler en conséquence. "Succès du rappel () en cas de succès, échec du rappel () en cas d'échec."

Regardons un exemple de pointeur de fonction simple

void cbfunc()
{
     printf("called");
}

 int main ()
 {
                   /* function pointer */ 
      void (*callback)(void); 
                   /* point to your callback function */ 
      callback=(void *)cbfunc; 
                   /* perform callback */
      callback();
      return 0; 
}

Comment passer l'argument à la fonction de rappel?

Observé que le pointeur de fonction pour implémenter le rappel prend en vide *, ce qui indique qu'il peut accepter tout type de variable, y compris la structure. Vous pouvez donc passer plusieurs arguments par structure.

typedef struct myst
{
     int a;
     char b[10];
}myst;

void cbfunc(myst *mt) 
{
     fprintf(stdout,"called %d %s.",mt->a,mt->b); 
}

int main() 
{
       /* func pointer */
    void (*callback)(void *);       //param
     myst m;
     m.a=10;
     strcpy(m.b,"123");       
     callback = (void*)cbfunc;    /* point to callback function */
     callback(&m);                /* perform callback and pass in the param */
     return 0;   
}
Sachin Mhetre
la source
2

Un rappel est une méthode dont l'exécution est planifiée lorsqu'une condition est remplie.

Un exemple «réel» est un magasin de jeux vidéo local. Vous attendez Half-Life 3. Au lieu d'aller au magasin tous les jours pour voir si c'est le cas, vous enregistrez votre email sur une liste pour être averti lorsque le jeu sera disponible. L'e-mail devient votre "rappel" et la condition à remplir est la disponibilité du jeu.

Un exemple de "programmeurs" est une page Web où vous souhaitez effectuer une action lorsqu'un bouton est cliqué. Vous enregistrez une méthode de rappel pour un bouton et continuez à effectuer d'autres tâches. Lorsque / si l'utilisateur clique sur le bouton, le navigateur examinera la liste des rappels pour cet événement et appellera votre méthode.

Un rappel est un moyen de gérer les événements de manière asynchrone. Vous ne pouvez jamais savoir quand la fonction de rappel sera exécutée ou si elle sera exécutée du tout. L'avantage est qu'il libère vos cycles de programme et de CPU pour effectuer d'autres tâches en attendant la réponse.

Optimiste
la source
Dire qu'il est "programmé" pourrait créer de la confusion ici. Les rappels sont souvent utilisés dans les systèmes asynchrones et il n'y aurait pas de "planification" mais plutôt un "événement" qui déclenche le rappel à exécuter.
Deven Phillips
2

Clair et simple: Un rappel est une fonction que vous donnez à une autre fonction, afin qu'elle puisse l' appeler .

Habituellement, il est appelé lorsqu'une opération est terminée. Puisque vous créez le rappel avant de le donner à l'autre fonction, vous pouvez l'initialiser avec les informations de contexte du site d'appel. C'est pourquoi elle est appelée un rappel * - la première fonction rappelle dans le contexte d'où elle a été appelée.

Andrei Vajna II
la source
2

«En programmation informatique, un rappel est une référence à du code exécutable, ou un morceau de code exécutable, qui est passé comme argument à un autre code. Cela permet à une couche logicielle de niveau inférieur d'appeler un sous-programme (ou une fonction) défini dans une couche de niveau supérieur. » - Wikipédia

Rappel en C à l'aide du pointeur de fonction

En C, le rappel est implémenté à l'aide du pointeur de fonction. Pointeur de fonction - comme son nom l'indique, est un pointeur sur une fonction.

Par exemple, int (* ptrFunc) ();

Ici, ptrFunc est un pointeur vers une fonction qui ne prend aucun argument et retourne un entier. N'OUBLIEZ PAS de mettre entre parenthèses, sinon le compilateur supposera que ptrFunc est un nom de fonction normal, qui ne prend rien et renvoie un pointeur sur un entier.

Voici du code pour illustrer le pointeur de fonction.

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

Essayons maintenant de comprendre le concept de rappel en C à l'aide du pointeur de fonction.

Le programme complet a trois fichiers: callback.c, reg_callback.h et 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)();                               
}

Si nous exécutons ce programme, la sortie sera

Ceci est un programme démontrant la fonction de rappel à l'intérieur de register_callback à l'intérieur de my_callback à l'intérieur du programme principal

La fonction de couche supérieure appelle une fonction de couche inférieure comme un appel normal et le mécanisme de rappel permet à la fonction de couche inférieure d'appeler la fonction de couche supérieure via un pointeur vers une fonction de rappel.

Rappel en Java à l'aide de l'interface

Java n'a pas le concept de pointeur de fonction Il implémente le mécanisme de rappel via son mécanisme d'interface Ici, au lieu d'un pointeur de fonction, nous déclarons une interface ayant une méthode qui sera appelée lorsque l'appelé aura terminé sa tâche

Permettez-moi de le démontrer à travers un exemple:

L'interface de rappel

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

L'appelant ou la classe de niveau supérieur

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 fonction Callee ou la couche inférieure

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

Rappel à l'aide du modèle EventListener

  • Élément de liste

Ce modèle est utilisé pour notifier de 0 à n nombres d'observateurs / auditeurs qu'une tâche particulière est terminée

  • Élément de liste

La différence entre le mécanisme de rappel et le mécanisme EventListener / Observer est que dans le rappel, l'appelé notifie l'appelant unique, tandis que dans Eventlisener / Observer, l'appelé peut notifier toute personne intéressée par cet événement (la notification peut aller à d'autres parties de la application qui n'a pas déclenché la tâche)

Permettez-moi de l'expliquer à travers un exemple.

L'interface d'événement

public interface Events {

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

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

Bouton de classe

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

Case à cocher 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 d'activité

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

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

Comme vous pouvez le voir dans le code ci-dessus, nous avons une interface appelée événements qui répertorie essentiellement tous les événements qui peuvent se produire pour notre application. La classe Widget est la classe de base pour tous les composants de l'interface utilisateur comme Button, Checkbox. Ces composants d'interface utilisateur sont les objets qui reçoivent réellement les événements du code d'infrastructure. La classe de widgets implémente l'interface d'événements et possède également deux interfaces imbriquées, à savoir OnClickEventListener et OnLongClickEventListener

Ces deux interfaces sont responsables de l'écoute des événements qui peuvent se produire sur les composants d'interface utilisateur dérivés du widget comme Button ou Checkbox. Donc, si nous comparons cet exemple avec l'exemple de rappel précédent utilisant l'interface Java, ces deux interfaces fonctionnent comme l'interface de rappel. Ainsi, le code de niveau supérieur (Here Activity) implémente ces deux interfaces. Et chaque fois qu'un événement se produit sur un widget, le code de niveau supérieur (ou la méthode de ces interfaces implémentées dans le code de niveau supérieur, qui est ici Activity) sera appelé.

Permettez-moi maintenant de discuter de la différence de base entre le modèle de rappel et le programme d'écoute d'événements. Comme nous l'avons mentionné, en utilisant le rappel, l'appelé ne peut notifier qu'un seul appelant. Mais dans le cas du modèle EventListener, toute autre partie ou classe de l'application peut s'enregistrer pour les événements qui peuvent se produire sur le bouton ou la case à cocher. L'exemple de ce type de classe est l'AutreClasse. Si vous voyez le code de OtherClass, vous constaterez qu'il s'est enregistré en tant qu'écouteur à ClickEvent qui peut se produire dans le bouton défini dans l'activité. La partie intéressante est que, outre l'activité (l'appelant), cette OtherClass sera également notifiée chaque fois que l'événement de clic se produit sur le bouton.

somenath mukhopadhyay
la source
1

Les rappels vous permettent d'insérer votre propre code dans un autre bloc de code à exécuter à un autre moment, ce qui modifie ou ajoute au comportement de cet autre bloc de code en fonction de vos besoins. Vous gagnez en flexibilité et en personnalisation tout en ayant un code plus facile à gérer.

Moins de hardcode = plus facile à entretenir et à changer = moins de temps = plus de valeur commerciale = génialité.

Par exemple, en javascript, en utilisant Underscore.js, vous pouvez trouver tous les éléments pairs dans un tableau comme celui-ci:

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> [2, 4, 6]

Exemple reproduit avec l'aimable autorisation de Underscore.js: http://documentcloud.github.com/underscore/#filter

letuboy
la source
1

[édité] quand nous avons deux fonctions disons functionA et functionB , si functionA dépend de functionB .

nous appelons ensuite functionB comme fonction de rappel. Ceci est largement utilisé dans le framework Spring.

fonction de rappel exemple wikipedia

Balaswamy Vaddeman
la source
1

Considérez une méthode comme confiant une tâche à un collègue. Une tâche simple pourrait être la suivante:

Solve these equations:
x + 2 = y
2 * x = 3 * y

Votre collègue fait le calcul avec diligence et vous donne le résultat suivant:

x = -6
y = -4

Mais votre collègue a un problème, il ne comprend pas toujours les notations telles que ^, mais il les comprend par leur description. Tels que exponent. Chaque fois qu'il en trouve un, vous récupérez ce qui suit:

I don't understand "^"

Cela vous oblige à réécrire l'ensemble de vos instructions après avoir expliqué ce que le personnage signifie pour votre collègue, et il ne se souvient pas toujours entre les questions. Et il a du mal à se souvenir de vos conseils aussi, comme me le demander. Il suit toujours vos instructions écrites du mieux qu'il peut cependant.

Vous pensez à une solution, vous ajoutez simplement ce qui suit à toutes vos instructions:

If you have any questions about symbols, call me at extension 1234 and I will tell you its name.

Maintenant, chaque fois qu'il a un problème, il vous appelle et vous demande, plutôt que de vous donner une mauvaise réponse et de redémarrer le processus.

Guvante
la source
0

Cela en termes de téléchargement d'une page Web:

Votre programme fonctionne sur un téléphone portable et demande la page Web http://www.google.com . Si vous écrivez votre programme de manière synchrone, la fonction que vous écrivez pour télécharger les données s'exécutera en continu jusqu'à ce que toutes les données soient téléchargées. Cela signifie que votre interface utilisateur ne sera pas actualisée et apparaîtra essentiellement figée. Si vous écrivez votre programme à l'aide de rappels, vous demandez les données et dites «exécutez cette fonction lorsque vous avez terminé». Cela permet à l'interface utilisateur d'autoriser l'interaction de l'utilisateur pendant le téléchargement du fichier. Une fois le téléchargement de la page Web terminé, votre fonction de résultat (rappel) est appelée et vous pouvez gérer les données.

Fondamentalement, il vous permet de demander quelque chose et de continuer à exécuter en attendant le résultat. Une fois que le résultat vous est retourné via une fonction de rappel, vous pouvez reprendre l'opération là où elle s'était arrêtée.

sokket
la source