Groovy中带有默认值的命名参数

28

在Groovy中是否可以使用具有默认值的命名参数?我的计划是创建一种对象工厂,可以不带任何参数调用它以获取带有默认值的对象。此外,我需要能够显式设置对象的任何参数。例如,在Python中使用关键字参数就可以实现这一点。

我现在正在尝试的代码类似于以下内容:

// 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

我正在开发的真实应用程序将有更多的参数,因此需要更多的组合。

谢谢

更新:

我计划使用工厂方法进行测试。不能真正触及Foo类,尤其是它的默认值。

@dmahapatro和@codelarks在下面的回答中提出了使用Map作为参数的好方法,这给了我一个可能解决方案的想法。我可以创建一个具有所需默认值并覆盖所需值的map,并将其传递给工厂方法。这可能会完成任务,我将采用这种方法,除非我得到更好的建议。

我的当前方法如下:

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'] )

注意:左移操作(<<)会修改原始地图,因此在上面的示例中,年龄也将在最后一个方法调用中为21岁。在我的情况下,这不是问题,因为默认地图可以在每次设置方法中重新创建。


不要那样做。defaults 在这种情况下维护状态。将其设为本地的。请查看我的更新。 - dmahapatro
我确实意识到了,因此在我的更新中有注释。无论如何,使用函数本地映射来设置默认值是一种更好的方法。感谢您的提示。 - kaskelotti
1个回答

38

Groovy默认为您执行此操作(映射构造函数)。 您不需要工厂方法。 这是一个例子

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)

更新
@codelark的占星学 :). 如果该类无法访问以设置默认值,则可以执行以下操作

@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)

5
如果出于某些原因你不想使用地图构造函数,你可以按照上述方式创建一个只有一个地图参数的函数,从而实现相同的功能。 - codelark
1
我已经更新了我的问题并添加了这些细节,但是我也会在这里为您添加。该方法是用于测试目的,因此我不能触及实际Foo类的默认值。 - kaskelotti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接