Limitaciones de las clases anónimas de Java en comparación con los bloques de Objective-C

Estoy empezando a envolver mi cabeza en torno a las funciones y cierres de primer orden después de descubrir bloques en Objective-C. Java es otro lenguaje donde he escuchado sobre cierres (o falta de ellos) y cómo las clases anónimas compensan esto un poco.

Definitivamente puedo ver las ventajas de los cierres como bloques en Objective-C, pero ¿cuáles son las limitaciones de las clases anónimas de Java? ¿Hasta qué punto compensan un poco la falta de verdaderos cierres?

Las clases anónimas de Java son muy, muy verbosas. Además de las vastas cantidades de repeticiones que necesita solo para definirlas, algunas de las decisiones de diseño de Java implican que muchas tareas comunes son mucho más detalladas que en otros idiomas. Por ejemplo, importar valores ascendentes mutables en el cierre es un problema en Java.

Básicamente, Java no soporta upvalues; en su lugar, se simulan pasándolos (por valor) a la clase a través de parámetros invisibles al constructor de la clase. Debido a que se pasan por valor, modificarlos dentro de la clase no afectará la copia en el método que construyó la clase, por lo que el comstackdor hace que los declare definitivos para evitar confundirse. p.ej:

Runnable function() { final int i = 4; return new Runnable() { public void run() { System.out.println("i="+i); // can't modify i here } } } 

En ocasiones en las que necesite modificar la variable, por ejemplo, en casi todos los casos en que los cierres serían útiles, debe hacer trampa:

 Runnable function() { final int[] i = new int[1]; i[0] = 4; return new Runnable() { public void run() { System.out.println("i="+i[0]); i[0] = i[0] + 1; } } } 

Aquí, i mismo sigue siendo inmutable, pero como apunta a un objeto mutable, puedo cambiar el contenido del objeto. (Naturalmente, en la vida real usaría una clase en lugar de una matriz, porque el uso de matrices es realmente feo. Y eso lo hace aún más prolijo).

Supongo que la próxima versión de Java tendrá azúcar sintáctico para hacer todo esto más fácil, pero en este momento la progtwigción centrada en el cierre es bastante incómoda en Java. A menudo me resulta más fácil cambiar la lógica de no usar cierres, simplemente para permitirme mantener la cantidad de código en uso lo suficientemente pequeña como para que sea comprensible.

Realmente no conozco la versión de cierre de Objetivo C, pero las conozco de Smalltalk y Lua.

Un cierre es esencialmente una función que tiene acceso a una variable local de alguna otra función / bloque (generalmente una en la que el cierre está nested sintácticamente). De esta manera, la variable local puede vivir más tiempo que el bloque en el que se define. Cuando tiene varios cierres sobre la misma variable, pueden comunicarse utilizando esta variable.

Las clases locales de Java (de las cuales las clases anónimas son un caso especial) admiten una versión limitada de esto: permiten el acceso a una variable final , es decir, una variable que no puede cambiar su valor. Esto se implementa copiando el valor de esta variable en el objeto de clase local en su construcción. Puede emular cierres reales utilizando un objeto mutable en esta variable (en el caso más simple, una matriz de un elemento).

Además, la syntax de Java para esto es bastante fea, pero encaja perfectamente con el rest del lenguaje, y permite la seguridad de tipo estático (al contrario de algunas variantes de syntax más cortas que se analizan).

    Intereting Posts