Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy named and default arguments

Groovy supports both default, and named arguments. I just dont see them working together.

I need some classes to support construction using simple non named arguments, and using named arguments like below:

def a1 = new A(2)
def a2 = new A(a: 200, b: "non default")

class A extends SomeBase {
    def props
    A(a=1, b="str") { 
        _init(a, b)
    }

    A(args) { 
       // use the values in the args map:
       _init(args.a, args.b)
       props = args
    }

    private _init(a, b) {
    }

}

Is it generally good practice to support both at the same time? Is the above code the only way to it?

like image 737
Ayman Avatar asked Sep 14 '11 11:09

Ayman


People also ask

Does Groovy have named parameters?

Groovy collects all named parameters and puts them in a Map. The Map is passed on to the method as the first argument.

What does [:] mean in Groovy?

[:] creates an empty Map. The colon is there to distinguish it from [] , which creates an empty List. This groovy code: def foo = [:]

What is args in Groovy?

On lines 6-9, we call the parse() method of the CliBuilder instance cli, passing the args—an array of String values created by the Groovy run-time and containing the arguments from the command line.

How do you call a method in Groovy?

In Groovy, we can add a method named call to a class and then invoke the method without using the name call . We would simply just type the parentheses and optional arguments on an object instance. Groovy calls this the call operator: () . This can be especially useful in for example a DSL written with Groovy.


1 Answers

The given code will cause some problems. In particular, it'll generate two constructors with a single Object parameter. The first constructor generates bytecode equivalent to:

A() // a,b both default
A(Object) // a set, b default
A(Object, Object) // pass in both

The second generates this:

A(Object) // accepts any object

You can get around this problem by adding some types. Even though groovy has dynamic typing, the type declarations in methods and constructors still matter. For example:

A(int a = 1, String b = "str") { ... }
A(Map args) { ... }

As for good practices, I'd simply use one of the groovy.transform.Canonical or groovy.transform.TupleConstructor annotations. They will provide correct property map and positional parameter constructors automatically. TupleConstructor provides the constructors only, Canonical applies some other best practices with regards to equals, hashCode, and toString.

like image 167
ataylor Avatar answered Sep 24 '22 16:09

ataylor