named parameters with default values in groovy
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)
Related videos on Youtube
Comments
-
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 almost 11 yearsDon't do that.
defaults
maintains state in this case. Make it local. See my update. -
kaskelotti almost 11 yearsI 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 almost 11 yearsand 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 almost 11 yearsI 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.