74

I would like to write a wrapper method for a webservice, the service accepts 2 mandatory and 3 optional parameters.

To have a shorter example, I would like to get the following code working

def myMethod(pParm1='1', pParm2='2') {
    println "${pParm1}${pParm2}"
}

myMethod();
myMethod('a')
myMethod(pParm2:'a') // doesn't work as expected
myMethod('b','c')

The output is:

12
a2
[pParm2:a]2
a2
bc

What I would like to achieve is to give one parameter and get 1a as the result. Is this possible (in the laziest way)?

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Chris
  • 1,119
  • 1
  • 8
  • 26

6 Answers6

100

Can't be done as it stands... The code

def myMethod(pParm1='1', pParm2='2'){
    println "${pParm1}${pParm2}"
}

Basically makes groovy create the following methods:

Object myMethod( pParm1, pParm2 ) {
    println "$pParm1$pParm2"
}

Object myMethod( pParm1 ) {
    this.myMethod( pParm1, '2' )
}

Object myMethod() {
    this.myMethod( '1', '2' )
}

One alternative would be to have an optional Map as the first param:

def myMethod( Map map = [:], String mandatory1, String mandatory2 ){
    println "${mandatory1} ${mandatory2} ${map.parm1 ?: '1'} ${map.parm2 ?: '2'}"
}

myMethod( 'a', 'b' )                // prints 'a b 1 2'
myMethod( 'a', 'b', parm1:'value' ) // prints 'a b value 2'
myMethod( 'a', 'b', parm2:'2nd')    // prints 'a b 1 2nd'

Obviously, documenting this so other people know what goes in the magical map and what the defaults are is left to the reader ;-)

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • Thanks, thinks looks like a way to go. I'll give it a shot and compare it with the effort when I use NULL values as default for optional parameters. Coming over from the java world I'm quite used to that... – Chris Aug 09 '13 at 17:02
  • Am I right, signature of the myMethod should be `def myMethod(String mandatory1, String mandatory2, Map map = [:])`? – Фима Гирин Jan 23 '17 at 13:15
  • 1
    Nope, other way round, as in the answer – tim_yates Jan 23 '17 at 13:17
  • the thing with the map is mentioned here: http://groovy-lang.org/objectorientation.html#_positional_parameters and http://groovy-lang.org/objectorientation.html#_named_parameters – Andreas Covidiot Mar 30 '20 at 10:36
  • how optional Map as first parm work ? is there any documentation for this? – Marslo Jun 17 '23 at 00:26
45

You can use arguments with default values.

def someMethod(def mandatory,def optional=null){}

if argument "optional" not exist, it turns to "null".

Alex
  • 673
  • 6
  • 9
5

Just a simplification of the Tim's answer. The groovy way to do it is using a map, as already suggested, but then let's put the mandatory parameters also in the map. This will look like this:

def someMethod(def args) {
    println "MANDATORY1=${args.mandatory1}"
    println "MANDATORY2=${args.mandatory2}"
    println "OPTIONAL1=${args?.optional1}"
    println "OPTIONAL2=${args?.optional2}"
}

someMethod mandatory1:1, mandatory2:2, optional1:3

with the output:

MANDATORY1=1
MANDATORY2=2
OPTIONAL1=3
OPTIONAL2=null

This looks nicer and the advantage of this is that you can change the order of the parameters as you like.

Catalin
  • 366
  • 2
  • 8
3

We can Deal with Optional parameters in 2 ways

  1. Creating the method parameter with null values:
def generateReview(def id, def createDate=null) {
     return new Review(id, createDate ?: new Date()) // ?: short hand of ternary operator
    }

generateReview(id) // createDate is not passed
generateReview(id, createDate) // createDate is passed
  1. Using Java Optional.of()
def generateReview(def id, Optional<Date> createDate) {
     return new Review(id, createDate.isPresent() ? createDate.get() : new Date())
    }

generateReview(id, Optional.empty()) // createDate is not passed
generateReview(id, Optional.of(createDate)) // createDate is passed
Md. Shahariar Hossen
  • 1,367
  • 10
  • 11
0

This question, quiet old, it is still searched and relevant. Some previous answers are giving solutions more related with Java but the questions is for Groovy and then you can use named parameters that let you provide default values for them. But, the most useful solution is pass a Map as first parameter and, as commented in the [documentation of Groovy][1]:

When the first argument is a Map, Groovy combines all named parameters into a Map (regardless of ordering) and supplies the map as the first parameter. This can be a good approach if your properties are declared as final (since they will be set in the constructor rather than after the fact with setters).

So you can provide as many optional parameters as you want as named parameters and, inside the function, give them default values if you want.

[1]: http://groovy-lang.org/objectorientation.html#:~:text=When%20the%20first,fact%20with%20setters).

0

Had this problem for a Jenkinsfile.

You have 2 Options:

  • Using Named Parameter
  • Using Positioned Parameter

Named Parameter

def shouldDeploy(Map args) {
  def isBuilt = args.isBuilt ?: false
  def optional = args.optional ?: true
  echo "isBuilt: ${isBuilt}"
  echo "optional: ${optional}"
  return isBuilt && optional
}

and call it like this: shouldDeploy(isBuilt: true, optional: true)

Positioned Parameter

def shouldDeploy(isBuilt, optional=true) {
    echo "isBuilt: ${isBuilt}"
    echo "optional: ${optional}"
    return isBuilt && optional
}

and call it like this: shouldDeploy(true, true)

papierkorp
  • 31
  • 3