しおしお

IntelliJ IDEAのことなんかを書いてます

Closureのプロパティ値を任意のオブジェクトのプロパティにコピーしてみた

Gradleのcopyメソッドやfilesetって、引数でもらったクロージャの値をどうやって使ってるんだろうって気になってGradleやGroovyのコードを眺めてたらなんとなくわかったような気がしてた。

ちゃんと理解してるとは思えないけど、わかったことはClosureのdelegateプロパティに設定したオブジェクトに対して値の設定や逆に値の取得ができたりするようです。

少し試してみたので、コードと実行結果をアップします。

値をコピーしたいクラス

class ClosureTest {
  def hoge1
  def hoge2
  def hoge3

  def hoge1(def hoge1) {
    this.hoge1 = hoge1;
    this
  }
  def hoge2(def hoge2) {
    this.hoge2 = hoge2;
    this
  }
  def hoge3(String... hoge3) {
    this.hoge3 = hoge3;
    this
  }

  @Override
  public String toString() {
    return "TestHoge{" +
            "hoge1=" + hoge1 +
            ", hoge2=" + hoge2 +
            ", hoge3=" + hoge3 +
            '}';
  }
}

クロージャを使って値をコピーするコード

def test(Closure c) {

  // 値を移送する場合は、Closure.DELEGATE_FIRSTを設定する
  c.resolveStrategy = Closure.DELEGATE_FIRST

  def test1 = new ClosureTest(hoge1: "hoge1", hoge2: "hoge2", hoge3: "hoge3")

  println "pre test1 = ${test1}"

  // delegateプロパティに値を設定したいオブジェクトを設定する。
  c.delegate = test1

  // delegateオブジェクトに値をコピーする場合は、Closure.DELEGATE_FIRSTを設定する。
  c.resolveStrategy = Closure.DELEGATE_FIRST

  c.call()

  println "after test1 = ${test1}"

}

println "パターン1:一部のプロパティに値を設定"
test {
  hoge1 "ほげ1"
}
println ""
println "パターン2:全てのプロパティに値を設定"
test {
  hoge1 "ほげ1"
  hoge2 "ほげ2"
  hoge3 '可変', '引数'
}

実行結果

パターン1ではhoge1のみ値が移送され、その他の項目が変更されていないことが確認できます。
パターン2では全ての項目が移送されているのが確認できます。

パターン1:一部のプロパティに値を設定
pre test1 = TestHoge{hoge1=hoge1, hoge2=hoge2, hoge3=hoge3}
after test1 = TestHoge{hoge1=ほげ1, hoge2=hoge2, hoge3=hoge3}

パターン2:全てのプロパティに値を設定
pre test1 = TestHoge{hoge1=hoge1, hoge2=hoge2, hoge3=hoge3}
after test1 = TestHoge{hoge1=ほげ1, hoge2=ほげ2, hoge3=[可変, 引数]}

試してはないですが、resolveStrategyに「Closure.OWNER_FIRST」を設定するとオブジェクトからクロージャに値がコピーされるようです。

クロージャがネストした場合とかはどうなるんだ?とかかなり理解不足ですが。。。この辺ちゃんと理解できてきたら、おれおれDSLとか作れるようになるのかな?

おわり。