2010-03-18 14 views
8

C'è qualche altro modo in java per implementare le richiamate oltre alle classi interne? Qual è la differenza tra callback e chiusure?Chiusura e callback

risposta

10

La chiusura è come lo si costruisce, il callback è come lo si utilizza.

Un callback può essere implementato come chiusura (in lingue che li hanno) o un'implementazione di un'interfaccia (in Java, come classe interna anonima o classe normale).

Callback significa che si passa una parte di codice a una funzione, in modo che la funzione possa chiamare quel codice successivamente. È un tipo speciale di parametro.

Il pezzo di codice può essere un puntatore a funzione o una chiusura o un oggetto con metodi ben noti, a seconda di ciò che offre la lingua.

+0

Questa era la risposta che stavo cercando di scrivere quando Neeraj lasciò cadere la domanda ma non riuscì a uscire in modo coerente. Complimenti. –

0

Non credo.

Se esiste, allora è probabilmente inferiore in qualche modo, altrimenti le classi interne anonime non sarebbero ampiamente utilizzate.

0

Non c'è differenza.

Le chiusure possono essere definite come un blocco di codice che tiene il contesto genitore che può essere eseguito con facilità.

In effetti, l'unica differenza che conosco tra questi è la facilità di scrittura. Una tipica chiusura groovy/ruby ​​è effettivamente più piccola da scrivere rispetto a una classe anonima Java.

Tuttavia, considerando Java framworks come guava e ci uso liberale di classi/interfacce anonimi, in particolare per le chiusure tipici casi d'uso come filter (a confronto con il groove di implementation), posso dire non c'è assolutamente nessuna differenza di progettazione.

+0

Se non c'è alcuna differenza, allora perché questi due nomi esistono. Io sono all'oscuro – Neeraj

0

Purtroppo l'unico modo ragionevole è classi interne/anonime.

Si può anche farlo con il riflesso, ma di solito è più lento e difficile nella manutenzione (nessuna evidenziazione della sintassi, riferimenti difficili da trovare in IDE ecc.). Un esempio:

myButton.addActionListener(EventHandler.create(ActionListener.class, handlerObject, "onClick")); 
1

Un callback è un qualsiasi codice eseguibile passato come parametro ad un altro codice. Nell'uso frequente, quel codice eseguibile è una chiusura, ma non è necessariamente.

La parola chiusura è in qualche modo abusata e molte persone lo usano come sinonimo di "funzione anonima", ma almeno lo according to Wikipedia, che è un uso improprio del termine. L'articolo di Wikipedia lo spiega meglio di quello che posso fare rapidamente.

5

Sia le chiusure che le classi interne anonime (e altre) possono essere utilizzate come richiamate. Un callback è solo un codice che viene passato come argomento ad un altro codice.

Una grande differenza di chiusure, rispetto alle classi interne anonime di Java, è che (in linguaggi imperativi) una chiusura può modificare le variabili dell'ambito circostante.Wikipedia fornisce il seguente esempio:

var f, g; 
function foo() { 
    var x = 0; 
    f = function() { return ++x; }; 
    g = function() { return --x; }; 
    x = 1; 
    alert('inside foo, call to f(): ' + f()); // "2" 
} 
foo(); 
alert('call to g(): ' + g()); // "1" 
alert('call to f(): ' + f()); // "2" 
+0

Sebbene questo possa essere emulato da 'final ObjRef x = new ObjRef (0);' con 'ObjRef' implementato come riferimento mutabile. –

+0

In realtà Scala fa qualcosa del genere per implementare chiusure sulla JVM, perché JVM (e Java) non le supportano in modo nativo. –

1

Se avete bisogno di chiusure in Java si potrebbe provare lambdaj. Here è possibile vedere come permette di definire chiusure attraverso un DSL molto semplice.

+1

In realtà, lambdaj non supporta la creazione di chiusure. Al massimo supporta la creazione di alcuni tipi di espressioni lambda che non sono chiusure. –

0

Ecco due implementazioni che utilizzano chiusure e callback.

Ed ecco un esempio migliore (lo trovate qui http://www.caglargonul.com/2013/04/10/is-it-really-a-closure-yes-it-is/) per comprendere ciò che la chiusura è. La chiave è che

una chiusura viene fornito con un ambiente di riferimento non solo un codice funzione.

Il modo migliore per implementare una chiusura in Java 7 e versioni successive è l'utilizzo di un'interfaccia. In questo esempio, una callback è implementata come chiusura.

Prima dichiari la tua interfaccia che manterrà la tua chiusura.

public interface CallBack { 
    void m(int e); 
} 

e permette aggiungere una classe responsabile per lo svolgimento di una serie di dispositivi di chiusura, due metodi comuni per l'aggiunta e la rimozione di chiusura e una funzione pubblica che chiamerà le funzioni all'interno delle chiusure quando si verifica un evento.

public class CCallBack { 

    List<CallBack> cbs = new ArrayList<>(); 

    public void registerCallBack(CallBack f){ 
     cbs.add(f); 
    } 

    public void removeCallBack(CallBack f){ 
     if(cbs.contains(f)){ 
      cbs.remove(f); 
     } 
    } 

    public void onAction(int i){ 
     for (CallBack callBack : cbs) { 
      callBack.m(i); 
     } 
    } 
} 

Ed ecco la parte magica. Guarda l'ambiente di riferimento in azione.

public class CallBackTester { 
    CCallBack cb = new CCallBack(); 

    @Test 
    public void test_callback(){ 

     CallBack cb1 = new CallBack() { 
      int x = 1; 
      @Override 
      public void m(int e) { 
       if(e==1){ 
        System.out.println("You register this callback " + x + " time/times"); 
        x++; 
       } 
      } 
     }; 

     cb.registerCallBack(cb1); 
     cb.registerCallBack(cb1); 
     cb.registerCallBack(cb1); 
     cb.removeCallBack(cb1); 

     cb.onAction(1); 
    } 

} 

Sopra quando dichiariamo cb1 stiamo aggiungendo un ambiente di riferimento costituito dalla variabile x. Quando chiamiamo la funzione all'interno di questa chiusura stiamo incrementando questa variabile di uno. Se fosse una funzione normale, x sarebbe stato dichiarato come 1 quando chiamiamo la funzione. MA NON È UNA FUNZIONE NORMALE. È UNA CHIUSURA. Quindi x non viene dichiarato ogni volta che chiamiamo la funzione nella chiusura. Come puoi vedere dall'output ogni volta che lo chiamiamo, x sta aumentando.

You register this callback 1 time/times 
You register this callback 2 time/times