web-dev-qa-db-ja.com

groovyのデフォルト値を持つ名前付きパラメーター

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をパラメーターとして使用することで、可能な解決策のアイデアを与えてくれました。必要なデフォルトでマップを作成し、必要な値をオーバーライドして、それをファクトリメソッドに渡すことができます。これでうまくいくと思いますが、より良いアプローチのヒントが得られない限り、私はそれで行きます。

以下の私の現在のアプローチ

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

注: leftShift操作(<<)は元のマップを変更するため、上記の例では、最後のメソッド呼び出しでも年齢は21になります。私の場合、デフォルトのマップはセットアップメソッドで毎回新しく作成できるため、これは問題ではありません。

23
kaskelotti

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)
32
dmahapatro