2010-03-18 12 views
8

¿Hay alguna otra forma en Java para implementar las llamadas de regreso aparte de las clases internas? ¿Cuál es la diferencia entre las devoluciones de llamada y los cierres?Cierre y devoluciones de llamada

Respuesta

10

El cierre es la forma de compilarlo, la retrollamada es la forma de usarlo.

Una devolución de llamada se puede implementar como un cierre (en los idiomas que los tienen) o una implementación de una interfaz (en Java, como una clase interna anónima o una clase regular).

La devolución de llamada significa que pasa un fragmento de código a una función, de modo que la función puede llamar a esa parte del código más tarde. Es un tipo especial de parámetro.

El fragmento de código puede ser un puntero de función o un cierre o un objeto con métodos bien conocidos, dependiendo de lo que ofrece el lenguaje.

+0

Esta fue la respuesta que estaba tratando de escribir cuando Neeraj por primera vez soltó la pregunta, pero no pudo salir de manera coherente. Prestigio. –

0

No lo creo.

Si existe, entonces es probable que sea inferior de alguna manera, de lo contrario las clases internas anónimas no serían ampliamente utilizadas.

0

No hay diferencia.

Los cierres se pueden definir como un bloque de código que contiene el contexto primario que se puede ejecutar con facilidad.

De hecho, la única diferencia que conozco entre ellos es la facilidad de escribir. Un cierre groovy/ruby ​​típico es de hecho más pequeño para escribir que una clase anónima de Java.

Sin embargo, teniendo en cuenta Java framworks como guava y hay un uso liberal de clases/interfaces anónimos, particularmente para cierres típicos casos de uso como filter (comparando con maravilloso de implementation), puedo decir que no hay absolutamente ninguna diferencia de diseño.

+0

Si no hay diferencia, entonces ¿por qué existen estos dos nombres? Estoy desorientado – Neeraj

0

Lamentablemente, la única manera razonable es de clases internas/anónimas.

También puede hacerlo con la reflexión, pero eso generalmente es más lento y más difícil en el mantenimiento (sin resaltado de sintaxis, referencias difíciles de encontrar en IDE, etc.). Un ejemplo:

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

Una devolución de llamada es cualquier código ejecutable que se pasa como parámetro a otro código. En el uso frecuente, ese código ejecutable es un cierre, pero no necesariamente.

El cierre de la palabra está algo maltratado y mucha gente simplemente lo usa como sinónimo de "función anónima", pero al menos according to Wikipedia, eso es un uso indebido del término. El artículo de Wikipedia explica esto mejor de lo que puedo hacer rápidamente.

5

Tanto los cierres como las clases internas anónimas (y otras) se pueden usar como devoluciones de llamada. Un callback es solo un código que se pasa como argumento a otro código.

Una gran diferencia de cierres, en comparación con las clases internas anónimas de Java, es que (en idiomas imperativos) un cierre puede modificar las variables del ámbito circundante.Wikipedia da el siguiente ejemplo:

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

Aunque esto puede ser emulado por 'ObjRef x = ObjRef (0);' con 'ObjRef' implementado como referencia mutable. –

+0

En realidad, Scala hace algo así para implementar cierres en la JVM, porque JVM (y Java) no los admite de forma nativa. –

1

Si necesita cierres en java que podría intentar lambdaj. Here puede ver cómo permite definir cierres a través de una DSL muy directa.

+1

En realidad, lambdaj no admite la creación de cierres. En el mejor de los casos, admite la creación de algunos tipos de expresiones lambda que no son cierres. –

0

Aquí hay dos implementaciones que usan cierres y devoluciones de llamada.

Y aquí es un ejemplo mejor (se puede encontrar aquí http://www.caglargonul.com/2013/04/10/is-it-really-a-closure-yes-it-is/) para comprender lo que es el cierre. La clave es que

un cierre viene con un entorno de referencia no solo un código de función.

La mejor forma de implementar un cierre en Java 7 y siguientes es mediante el uso de una interfaz. En este ejemplo, se implementa una devolución de llamada como cierre.

Primero declara su interfaz que sostendrá su cierre.

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

Y vamos a añadir una clase responsable de la celebración de una serie de cierres, dos métodos públicos para agregar y quitar los cierres y una función pública que llamar a las funciones dentro de los cierres cuando se produce 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); 
     } 
    } 
} 

Y aquí está la parte mágica. Ver el entorno de referencia en acción.

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

} 

Arriba cuando declaramos cb1 estamos agregando un entorno de referencia que consiste en la variable x. Cuando llamamos a la función dentro de este cierre estamos incrementando esta variable en uno. Si fuera una función normal, x habría sido declarado como 1 cuando llamemos a la función. PERO NO ES UNA FUNCIÓN NORMAL. ES UN CIERRE Entonces x no se declara cada vez que llamamos a la función en el cierre. Como puede ver en la salida cada vez que lo llamamos, x se está incrementando.

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