named parameters with default values in groovy

25,733

Groovy does that for you by default (map constructor). You would not need a factory method. Here is an example

import groovy.transform.ToString

@ToString(includeFields = true, includeNames = true)
class Foo{
    String name = "Default Name"
    int age = 25
    String address = "Default Address" 
}

println new Foo()
println new Foo(name: "John Doe")
println new Foo(name: "Max Payne", age: 30)
println new Foo(name: "John Miller", age: 40, address: "Omaha Beach")

//Prints
Foo(name:Default Name, age:25, address:Default Address)
Foo(name:John Doe, age:25, address:Default Address)
Foo(name:Max Payne, age:30, address:Default Address)
Foo(name:John Miller, age:40, address:Omaha Beach)

UPDATE
@codelark's astrology :). In case the class is not accessible to set default values, you can do like

@ToString(includeFields = true, includeNames = true)
class Bar{
    String name
    int age
    String address
}

def createBar(Map map = [:]){
    def defaultMap = [name:'John Doe',age:51,address:'High Street 11']
    new Bar(defaultMap << map)
}

println createBar()
println createBar(name: "Ethan Hunt")
println createBar(name: "Max Payne", age: 30)
println createBar(name: "John Miller", age: 40, address: "Omaha Beach")


//Prints
Bar(name:John Doe, age:51, address:High Street 11)
Bar(name:Ethan Hunt, age:51, address:High Street 11)
Bar(name:Max Payne, age:30, address:High Street 11)
Bar(name:John Miller, age:40, address:Omaha Beach)
Share:
25,733

Related videos on Youtube

kaskelotti
Author by

kaskelotti

SOreadytohelp

Updated on August 02, 2020

Comments

  • kaskelotti
    kaskelotti almost 4 years

    Is it possible to have named parameters with default values in groovy? My plan is to make a sort of object factory, which can be called with no arguments at all in order to get an object with default values. Also, I'd need the functionality to explicitly set any of the params for the object. I believe this is possible with Python keyword arguments, for example.

    The code I'm attempting with right now is something like below

    // Factory method
    def createFoo( name='John Doe', age=51, address='High Street 11') {
      return new Foo( name, age, address )
    }
    
    // Calls
    Foo foo1 = createFoo()  // Create Foo with default values
    Foo foo2 = createFoo( age:21 )  // Create Foo where age param differs from defaut
    Foo foo3 = createFoo( name:'Jane', address:'Low Street 11' )  // You get the picture
    // + any other combination available
    

    The real app that I'm working on will have a lot more of parameters and thus a lot more combinations needed.

    Thanks

    UPDATE:

    The factory method I'm planning is for testing purposes. Cannot really touch the actual Foo class and especially not it's default values.

    @dmahapatro and @codelarks answere below had a good point in using a Map as a param that gave me an idea of a possible solution. I could create a map with the wanted defaults and override the needed values, and pass that to the factory method. This'll probably do the job and I'll go with that, unless I get a hint of a better approach.

    My current approach below

    defaults = [ name:'john', age:61, address:'High Street']
    
    @ToString(includeFields = true, includeNames = true)
    class Foo {
      // Can't touch this :)
      def name = ''
      def age = 0
      def address = ''
    }
    
    def createFoo( Map params ) {
      return new Foo( params )
    }
    
    println createFoo( defaults )
    println createFoo( defaults << [age:21] )
    println createFoo( defaults << [ name:'Jane', address:'Low Street'] )
    

    NOTE: leftShift operation ( << ) modifies the the original map, so in the above example age will be 21 in the last method call as well. In my case, this is not a problem as the defaults map can be created freshly each time in setup method.

    • dmahapatro
      dmahapatro almost 11 years
      Don't do that. defaults maintains state in this case. Make it local. See my update.
    • kaskelotti
      kaskelotti almost 11 years
      I did realize that, hence the note in my update. Anyway, using a function local map for the defaults is a far better approach. Thanks for the tip.
  • codelark
    codelark almost 11 years
    and if for some reason you don't want to use the map constructor, you can create the function as above but with a single map parameter and accomplish the same thing.
  • kaskelotti
    kaskelotti almost 11 years
    I updated my question with these details, but I'll add them here for you to as well. The method is for testing purposes, so I cannot touch the default values of the actual Foo class.