Contribuye

Groovy persigue ser tan natural como sea posible para desarrolladores de Java, apunta la descripción del lenguaje Groovy en su sitio Web (http://groovy.codehaus.org/). Mencionan que prácticamente cualquier código escrito en Java podría definirse como código Groovy sin mayores sorpresas. Para quien aprende Groovy cuando no se tiene experiencia en Java este es sólo un artículo exótico, pero para quien comienza con Groovy y tiene experiencia con Java, las particularidades en diseño resaltarán más temprano que tarde. ¿Pero cuáles son las diferencias? Este artículo intenta listar las mayores diferencias entre Groovy y Java. Si los apreciables lectores conocen alguna otra que merezca atención y no se incluya, sírvase resaltarlo y seguir haciendo comunidad.

 

1. ==

En Java == con tipos primitivos significa usar igualdad, mientras que para tipos object significa comprobar identidad. Empero, en Groovy == siempre significa igual, es decir, el uso que la mayoría de los desarrolladores utiliza. En Groovy == aplica igualdad tanto para tipos primitivos como para tipos object y a lo largo de tipado estático y dinámico para simplificar las cosas.

Como ejemplo, si al trabajar con Java se quisiera mantener la semántica de igualdad para objetos, por ejemplo, haciendo tipado dinámico de la siguiente manera:

def x = 2 x 2
 if (x == 4) {
 ...
 }
 

Se obtendrían resultados inesperados, pues aunque se quisiera resolver una igualdad basada en el valor, Java lo resolvería por identidad. Es cierto, rara vez se usan comparaciones de identidad.

Si en Groovy se quisiera comparar identidades de los objetos, el método is() se proporciona para cada objeto:

if (x.is(4)) {
 ... // nunca true
 }
 

La condición de arriba nunca es true, ya que el objeto Integer en x (el cual es el resultado del cómputo de arriba), no es idéntico al objeto Integer con el valor 4 que se ha creado para la comparación.

2. Para declarar un arreglo no se puede escribir

int[] a = {1,2,3};
 

sino

int[] a = [1,2,3]
 

3. Si en Java solía escribir un loop similar a este:

for (int i=0; i < len; i++) {...}
 

en Groovy también puede usarlo, pero sólo se podrá usar una variable contadora. Alternativas a esto pueden ser:

for (i in 0..len-1) {...}
 

,

for (i in 0..

o

len.times {...}
 

4. in es una palabra reservada. No la use como nombre de variable.

 

Tenga en cuenta que:

  1. Los punto y coma son opcionales. Úselos si le agrada (aunque debe usarlos para poner varias sentencias en una línea).
  2. La palabra clave return es opcional.
  3. Puede usar la palabra clave this dentro de métodos estáticos (lo cual refiere a esta clase).
  4. Protected en Groovy tiene el mismo significado de protegido que en Java, p. ej., puede tener amigos en el mismo paquete y las clases derivadas pueden ver también a los miembros protegidos.
  5. Las clases interiroes no se soportan hasta ahora. En la mayoría de los casos puede usar clausuras (closures) en su lugar.
  6. La cláusula throws en una firma de método no se comprueba por el compilador de Groovy, pues no hay diferencia entre excepciones comprobadas y no comprobadas.
  7. No se obtendrán errores de compilación como se obtendrían en Java al usar miembros indefinidos o pasar argumentos de tipo incorrecto. De existir errores en el código se lanzarán excepciones en tiempo de ejecución, debido a la naturaleza dinámica de Groovy.

 

Características contra-intuitivas no tan comunes

Los programadores de Java están acostumbrados a usar punto y coma para terminar sentencias y a no tener clausuras (closures). También hay inicializadores de instancia en definiciones de clase. Así que podría ver algo como esto:

class Prueba {
   private final Algo algo = new Algo ( ) ;
   { algo.hazAlgunaCosa ( ) ; }
 }
 

Muchos programadores de Groovy evitan el uso del punto y coma pues es distractor y redundante (aunque otros lo utilizan todo el tiempo – es cuestión de estilo de código). Una situación que puede acarrear dificultades es escribir lo de arriba en Groovy así:

class Prueba {
   private final Algo algo = new Algo ( )
   { algo.hazAlgunaCosa ( ) }
 }
 

¡Esto lanzará un MissingMethodException!

El problema aquí es que en este ejemplo la nueva línea no es un terminador de sentencia, así que el siguiente bloque se trata como una clausura, la cual se pasa como un argumento al constructor Algo. Extrañísimo para muchos, pero cierto. Si desea usar inicializadores de instancia de esta manera, es preciso tener un punto y coma:

class Prueba {
   private final Algo algo = new Algo ( ) ;
   { algo.hazAlgunaCosa ( ) }
 }
 

De esta manera el siguiente bloque a la definición inicializada es claramente un inicializador de instancia.

comments powered by Disqus