web-dev-qa-db-fra.com

Qu'est-ce qu'une méthode de rappel en Java? (Le terme semble être utilisé librement)

Je ne comprends pas ce qu'est une méthode de rappel et j'ai entendu des gens utiliser ce terme très librement. Dans le monde Java, qu'est-ce qu'une méthode de rappel? Si quelqu'un pouvait fournir un exemple de code d'une méthode de rappel Java avec une explication, ce serait une excellente aide dans mon Java parcours d'apprentissage.

Merci d'avance.

31
Horse Voice

Un rappel est un morceau de code que vous passez en argument à un autre code afin qu'il l'exécute. Étant donné que Java ne prend pas encore en charge les pointeurs de fonction, ils sont implémentés en tant qu'objets Command. Quelque chose comme

public class Test {
    public static void main(String[] args) throws  Exception {
        new Test().doWork(new Callback() { // implementing class            
            @Override
            public void call() {
                System.out.println("callback called");
            }
        });
    }

    public void doWork(Callback callback) {
        System.out.println("doing work");
        callback.call();
    }

    public interface Callback {
        void call();
    }
}

Un rappel contiendra généralement une référence à un état pour être réellement utile.

En faisant en sorte que l'implémentation du rappel ait toutes les dépendances de votre code, vous gagnez une indirection entre votre code et le code qui exécute le rappel.

38

Une méthode de rappel dans Java est une méthode qui est appelée lorsqu'un événement (appelez-le E) se produit. Habituellement, vous pouvez l'implémenter en passant une implémentation d'une certaine interface à la système responsable du déclenchement de l'événement E (voir l'exemple 1).

De plus, dans les systèmes plus grands et plus complexes, vous pouvez simplement annoter une méthode et le système identifiera toutes les méthodes annotées et les appellera lorsque l'événement se produira (voir l'exemple 2). Bien sûr, le système définit les paramètres que la méthode doit recevoir et d'autres contraintes.

Exemple 1:

public interface Callback {
    //parameters can be of any types, depending on the event defined
    void callbackMethod(String aParameter);
}


public class CallbackImpl implements Callback {
    void callbackMethod(String aParameter) {
     //here you do your logic with the received paratemers
     //System.out.println("Parameter received: " + aParameter);

    }
}

//.... and then somewhere you have to tell the system to add the callback method
//e.g. systemInstance.addCallback(new CallbackImpl());

Exemple 2:

//by annotating a method with this annotation, the system will know which method it should call. 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CallbackAnnotation {}


public class AClass {

    @CallbackAnnotation
    void callbackMethod(String aParameter) {
     //here you do your logic with the received paratemers
     //System.out.println("Parameter received: " + aParameter);

    }
}

//.... and then somewhere you have to tell the system to add the callback class
//and the system will create an instance of the callback class
//e.g. systemInstance.addCallbackClass(AClass.class);
6
Andrei I

En termes simples ... En anglais simple, une fonction de rappel est comme un travailleur qui "rappelle" à son gestionnaire lorsqu'il a terminé une tâche.

En quoi sont-ils différents d'appeler une fonction d'une autre fonction en prenant du contexte dans la fonction appelante? Il est vrai que vous appelez une fonction d'une autre fonction, mais la clé est que le rappel est traité comme un Objet, afin que vous puissiez 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 rappel, 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
2
garvit94

En termes simples, le mécanisme de rappel fait référence à l'appel d'une fonction avec une autre fonction comme argument. Dans des langages comme C, C++, cela se fait en passant des pointeurs de fonction comme arguments mais Java n'a pas le concept de pointeurs. La solution de contournement est des interfaces. Nous transmettons des références aux interfaces au lieu des pointeurs. Votre la compréhension sera claire après avoir compris le code ci-dessous. Pour montrer également les applications du monde réel, imaginez l'achat d'une souris et d'un tapis de souris. Le prix du tapis de souris est fixe mais le prix de la souris diffère selon la marque.

interface mouse
{
    double mousePrice();
}
class BrandA implements mouse
{
    public double mousePrice()          //note that public access modifier is needed as all methods of interface are public are by default and when you override them
    //you cannot use any access modifier more restrictive
    {
        return 100;
    }

}

class BrandB implements mouse
{
    public double mousePrice()
    {
        return 200;
    }

}

class Simple
{
    static void total(mouse t)
    {
        double mousepad = 20;
        double mousep = t.mousePrice();
        System.out.println(mousepad + mousep);
    }
    public static void main(String args[])
    {
        mouse ob = new BrandA();        //upcasting. 
        total(ob);
    }
}
1
Mayank Agarwal