Argumentos Opcionales

La Sintáxis T... args en Java

Groovy soporta un número variable de argumentos. Esto es también posible en Java5 utilizando la sintáxis T... args. He aqui un ejemplo en Java que calcula el promedio de una lista de double:

~/Lgroovy/objects$ cat -n VarargsTest.java 
 1  public class VarargsTest 
 2  {
 3     // calculate average
 4     public static double average( double... numbers )
 5     {
 6        double total = 0.0; // initialize total
 7  
 8        // calculate total using the enhanced for statement
 9        for ( double d : numbers )              
10           total += d;                          
11  
12        return total / numbers.length;
13     } // end method average
14  
15     public static void main( String args[] ) 
16     {
17        double d1 = 10.0;
18        double d2 = 20.0;
19        double d3 = 30.0;
20        double d4 = 40.0;
21  
22        System.out.printf( "d1 = %.1f\nd2 = %.1f\nd3 = %.1f\nd4 = %.1f\n\n",
23           d1, d2, d3, d4 );
24  
25        System.out.printf( "Average of d1 and d2 is %.1f\n", 
26           average( d1, d2 ) ); 
27        System.out.printf( "Average of d1, d2 and d3 is %.1f\n", 
28           average( d1, d2, d3 ) );
29        System.out.printf( "Average of d1, d2, d3 and d4 is %.1f\n", 
30           average( d1, d2, d3, d4 ) );
31     } // end main
32  } // end class VarargsTest
Este es el resultado de una ejecución:
~/Lgroovy/objects$ java VarargsTest
d1 = 10,0
d2 = 20,0
d3 = 30,0
d4 = 40,0

Average of d1 and d2 is 15,0
Average of d1, d2 and d3 is 20,0
Average of d1, d2, d3 and d4 is 25,0

La Sintáxis T... args en Groovy

Funciona igual que en Java:

To use variable arguments in Groovy you have to give a special method signature where the last parameter is an array.

def foo(p1, ...., pn, T... args)

Here foo supports n arguments by default, but also an unspecified number of further arguments exceeding n.

Ejemplo:

~/Lgroovy/objects$ cat optionalArgs1.groovy 
def foo(Object... args) {
  args.length
}
println foo()
println foo(1,2)
println foo([1,2],3,4)
Ejecución:
~/Lgroovy/objects$ groovy optionalArgs1.groovy 
0
2
3

In this example we defined a method foo, that is able to take any number of arguments, including no arguments at all. args.length will then specify the number of arguments. T... is the same syntax as used in Java and is internally represented as array

La Sintáxis T[]

Groovy permite la sintáxis alternativa T[]:

~/Lgroovy/objects$ cat optionalArgs2.groovy 
def foo(Object[] args) {
  args.length
}
println foo()
println foo(1,2)
println foo([1,2],3,4)

Ejecución:

~/Lgroovy/objects$ groovy optionalArgs2.groovy 
0
2
3
That means any method that has an array as last parameter is seen by Groovy as a method that takes a variable number of arguments.

Caveats

This is no special logic we thought of, that is how variable arguments behave in Java too.

Ejemplo:

~/Lgroovy/objects$ cat -n optionalArgs3.groovy 
     1  def foo(Object[] args) {
     2    if (args == null) {
     3       println "args is null"
     4       0
     5    }
     6    else { 
     7      args.length
     8    }
     9  }
    10  foo(null)
    11  Object[] a = [1, 2]
    12  println a.class
    13  println foo(a)
    14  b = [1, 2]
    15  println b.class
    16  println foo(b)
Ejecución:
~/Lgroovy/objects$ groovy optionalArgs3.groovy 
args is null
class [Ljava.lang.Object;
2
class java.util.ArrayList
1

Dispatching Cuando Hay Sobrecarga y Número Variable de Argumentos

One more important point to mention is maybe a method overloaded with a method that takes variable arguments.

Groovy (and java) will select the most specific method,

Ejemplo:

~/Lgroovy/objects$ cat -n specific.groovy 
     1  def foo(Object[] args) {1}
     2  def foo (x) {2}
     3  def foo (x,y) {3}
     4  
     5  assert foo() == 1
     6  assert foo(1) == 2
     7  assert foo(1,2) == 3
     8  assert foo(1,1,1) == 1
     9  
    10  def x = [1,2] 
    11  assert foo(x) == 2
    12  
    13  // Coincide con la declaracion: def foo(Object[] args)
    14  def Object[]y = [1,2] 
    15  assert foo(y) == 1

Argumentos Variables y Argumentos con Valores por Defecto

El siguiente ejemplo muestra el comportamiento en un caso en el que se usa un argumento opcional con valor por defecto junto con la sintáxis T[]:

~/Lgroovy/objects$ cat -n optionalArgs4.groovy 
     1  def foo(c=8, Object[] args) {
     2    println "c = $c"
     3    args.length
     4  }
     5  println "num optional args = "+foo()
     6  println "num optional args = "+foo(6)
     7  println "num optional args = "+foo(4,5,6)
Ejecución:
~/Lgroovy/objects$ groovy optionalArgs4.groovy 
c = 8
num optional args = 0
c = 6
num optional args = 0
c = 4
num optional args = 2



Subsecciones
Casiano Rodríguez León
2010-04-30