Clausura - Tensho97/Aprende-a-Aprender GitHub Wiki
También llamada 'Clousure', una clausura es la combinación de una función y el contexto en el que se creó. Es decir, es una función externa que tiene otra función interna, la cual tiene acceso a las variables del scope en el que se ejecuta.
Para explicar lo que es un contexto usaremos el siguiente ejemplo:
function Hucha(monedas) {
var monedasGuardadas = 0;
monedasGuardadas += monedas;
document.write('La hucha tiene ' + monedasGuardadas + 'monedas');
}
Si ahora llamamos a la función pasándole 5 monedas (Hucha(5)
), se creará un contexto con el valor de las variables a las que esa función tiene acceso: monedasGuardadas
y monedas
.
Una vez se ha terminado de ejecutar la función, ese contexto es destruído y ya no tendríamos acceso a esas variables. En este código, la variable monedasGuardadas
siempre valdrá 0, y se le sumará el valor que le pasemos como parámetro.
Pero si por el contrario, hacemos lo mismo usando un clousure, obtenemos un resultado diferente:
function Hucha(nombre) {
var nombreHucha = nombre;
var monedasGuardadas = 0;
return function contarMonedas(monedas) {
monedasGuardadas += monedas;
document.write(nombreHucha + ' tiene ' + monedasGuardadas + 'monedas');
}
}
Ahora, la función que suma las monedas a las monedas guardadas es una función interna de la función Hucha(). De modo que contarMonedas()
tendrá acceso a las variables externas nombreHucha
y monedasGuardadas
. Si ahora llamamos a Hucha()
, el valor de monedasGuardadas no se perderá por cada llamada, ya que la función y su contexto no se destruyen una vez ejecutados.
Esto sucede porque se mantiene una referencia a las variables externas, que son visibles para la función interna.
En una clausura, toda variable local que sea necesaria para su funcionamiento, se quedará encerrada dentro de la propia clausura, y se guardarán con el valor que tenía la variable local cuando se produjo la salida de la función externa.
Cuando se invoca la función externa se genera una clausura. Cada clausura que se genere guarda sus propias referencias, es decir, no se guarda una única referencia para todos las clausuras. Una clausura es una combinación de función y de datos relativos al momento de su creación.
- Si en nuestra función anterior
Hucha()
creamos dos clausuras, veremos que cada una guarda sus propios valores y darán resultados diferentes:
var hucha1 = Hucha('hucha1'); //almacenamos las llamadas en variables
var hucha2 = Hucha('hucha2');
hucha1(5);
hucha1(15);
hucha2(5);
hucha2(40);
Resultado:
hucha1 tiene 5 monedas
hucha1 tiene 20 monedas
hucha2 tiene 5 monedas
hucha2 tiene 45 monedas
En un principio, Java no tenía un soporte sintáctico para realizar clausuras. Se han empezado a introducir a partir de Java 8. Lo común para imitar este comportamiento, era hacerlo mediante las Clases anónimas.
public class Comparador {
public static void main(String[] args) {
//una variable global usada por la clase interna
//fijarse que necesita ser "final"
final int numeroAComparar=10;
//clase anonima que actua como una clausura y usa la variable global
Comparator<Integer> comp=new Comparator<Integer>() {
public int compara(Integer a, Integer b) {
int resultado=0;
if (a<numeroAComparar) resultado = resultado - 1;
if (b<numeroAComparar) resultado = resultado + 1;
return resultado;
}
};
Integer[] array=new Integer[] {1,10, 5 , 15, 6 , 20, 21, 3, 7};
//llamada a un metodo que coge la clase anonima como parametro
Arrays.sort(array,comp);
for (int i:array) System.out.println(i);
}
}
Autora: Vanesa