6

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?

Ayman
  • 11,265
  • 16
  • 66
  • 92

1 Answers1

7

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.

Macke
  • 24,812
  • 7
  • 82
  • 118
ataylor
  • 64,891
  • 24
  • 161
  • 189
  • Unfortunately your URLs are now dead, but they should be found here: https://docs.groovy-lang.org/latest/html/gapi/groovy/transform/Canonical.html https://docs.groovy-lang.org/latest/html/gapi/groovy/transform/TupleConstructor.html – Ultimation Oct 29 '20 at 16:18
  • Links fixed now. :) – Macke Nov 21 '22 at 07:58