Callback (informática)
En programación de computadoras, una devolución de llamada o retrollamada (en inglés: callback) es una función "A" que se usa como argumento de otra función "B". Cuando se llama a "B", ésta ejecuta "A". Para conseguirlo, usualmente lo que se pasa a "B" es el puntero a "A".
Esto permite desarrollar capas de abstracción de código genérico a bajo nivel que pueden ser llamadas desde una subrutina (o función) definida en una capa de mayor nivel. Usualmente, el código de alto-nivel inicia con el llamado de alguna función, definida a bajo-nivel, pasando a esta un puntero, o un puntero inteligente (conocido como handle), de alguna función. Mientras la función de bajo-nivel se ejecuta, esta puede ejecutar la función pasada como puntero para realizar alguna tarea. En otro escenario, las funciones de bajo nivel registran las funciones pasadas como un handle y luego pueden ser usadas de modo asincrónico.
Una retrollamada puede ser usada como una aproximación simple al polimorfismo y a la programación genérica, donde el comportamiento de una función puede ser dinámicamente determinado por el paso punteros a funciones o handles a funciones de bajo nivel que aunque realicen tareas diferentes los argumentos sean compatibles entre sí. Esta es una técnica de mucha importancia por lo que se la llama código reutilizable.
Contenido |
[editar] Motivación
Para entender los motivos para usar retrollamadas, se puede considerar como ejemplo el problema de realizar varias operaciones arbitrarias en una lista. Una opción puede ser iterar sobre la lista, o también realizar alguna operación sobre cada uno de los elementos de la lista. En la práctica, la solución más común, pero no ideal, es utilizar iteradores como un bucle for) que deberá duplicarse en cada lugar del código donde sea necesario. Más aún, si la lista es actualizada por un proceso asíncrono (por ejemplo, si un elemento es añadido o eliminado), el iterador podría corromperse durante el paso a través de la lista.
Una alternativa podría ser crear una nueva biblioteca de funciones que ejecute la tarea deseada con la sincronización apropiada en cada caso. Esta propuesta aun requiere que cada nueva función de la biblioteca contenga el código para ir a través de la lista. Esta solución no es aceptable para bibliotecas genéricas que tengan como objetivo varias aplicaciones; el desarrollador de la biblioteca no puede anticiparse a las necesidades de cada aplicación, y el desarrollador de las aplicaciones no debería necesitar conocer los detalles de la implementación de la biblioteca.
En este caso las retrollamadas resuelven estos problemas. Un procedimiento es escribir el paso a través de una lista que provee a la aplicación del código para ir a través de la lista y operando sobre cada elemento. Existe una clara distinción entre la biblioteca y la aplicación sin sacrificar la flexibilidad. Una retrollamada puede también considerarse un tipo de rutina enlazada por referencia.
[editar] Ejemplo
El siguiente código en C muestra el uso de retrollamadas para el caso especifico de búsqueda de un elemento en un arreglo. En este caso, el primer entero es mayor que 5. Primero, el modelo de iteración:
int i; for (i = 0; i < celdas; i++) { if (arreglo[i] > 5) { break; } } if (i < celdas) { printf("Item %d\n", i); } else { printf("No encontrado\n"); }
Siguiente, vemos la implementación del código anterior como retrollamada:
/* CÓDIGO DE LA BIBLIOTECA */ int atravesCon(int arreglo[], size_t celdas, int (*callback)(int indice, int item, void *parametro), void *parametro) { int codigoSalida = 0; for (int i = 0; i < celdas; i++) { codigoSalida = callback(i, arreglo[i], parametro); if (codigoSalida != 0) { break; } } return codigoSalida; } /* CÓDIGO DE LA APLICACIÓN */ int buscar (int indice, int item, void *parametro) { if (item > 5) { *(int *)parametro = indice; return 1; } else { return 0; } } /* (en la otra función) */ int indice; int encontrado; encontrado = atravesCon(arreglo, celdas, &buscar, &indice); if (encontrado) { printf("Item %d\n", indice); } else { printf("No encontrado\n"); }
Noten que atravesCon recibe un parámetro extra que la retrollamada puede usar para sus propios propósitos. Normalmente una retrollamada utiliza tales parámetros como punteros a datos de la aplicación fuera de su ámbito, en este caso es la variable que recibe el índice. Esta característica sólo es necesaria para un lenguaje en el ámbito estático tales como C o C++. En C++ y otros lenguajes OO, otro tipo de soluciones son posibles.
[editar] Implementación
[editar] Casos especiales
[editar] Enlaces externos
- Style Case Study #2: Generic Callbacks
- C++ Callback Solution
- Basic Instincts: Implementing Callback Notifications Using Delegates
- Implement Script Callback Framework in ASP.NET
- Callback Balance C++ net framework
- Callback Procedures
- Implement callback routines in Java