13
10

More than 5 years have passed since last update.

[Groovy]with句を使ってオブジェクトの初期化をちょっと簡略化する

Posted at

概要

以下のような普通のクラスを用意します。

class Hello{
    String name
    Integer age
    String message

    def createMessage(String name, Integer age) {
       this.message = """Hello! I am ${name}(${age})"""
    }

    def setAge(Integer age) {
        this.age = age + 100
    }
}

特になんの変哲もないクラス。
少しJavaと違うのが、メンバ変数のセッタが宣言されている場合、Groovyの場合、直接プロパティにアクセスしようとすると、自動的にその変数用のセッタが呼ばれるということぐらいでしょうか?
例えばhelloObject.age = 100を実行すると、プロパティのアクセスではなく、setAgeが実行されます。

このオブジェクトを操作しようとすると、以下のような形になります。

def helloObject = new Hello()

helloObject.name = "koji"
helloObject.age = 29
helloObject.createMessage("koji", 29)

assert helloObject.name == "koji"
assert helloObject.age == 129
assert helloObject.message == 'Hello! I am koji(29)'

すごく普通です。
でもhelloObjectって毎回書くのって面倒くさくない?タイプミスとかあるとイライラするし。。。
ということで、with句の出番です。

with句を使って簡略化

def helloObject = new Hello()
helloObject.with {

    def hoge = 29

    name = "koji"
    age = hoge
    createMessage("koji", 29)

    //メソッドは以下の呼び方でも当然OK
    //createMessage "koji", 29
}

assert helloObject.name == "koji"
assert helloObject.age == 129
assert helloObject.message == 'Hello! I am koji(29)'

//with句内で宣言したローカル変数は外部で当然参照できない!素敵!
try {
    println hoge
} catch (groovy.lang.MissingPropertyException e){
    println e.toString()
}

オブジェクトに備わっているwithというメソッドに、そのオブジェクトに対して行いたい操作をクロージャとして渡してあげるだけです。
そのため、自身の変数名(helloObject)をわざわざ書かなくても良くなります。

メリット

当然オブジェクトの格納された変数名をwith句の中では書かなくていいのでソースがスッキリします。
また、オブジェクトに渡したい値などを計算したりする際に利用する一時変数がwith句外では参照できないのでwith句の外の世界を汚しません。今回の例だとhoge変数がそうですね。(個人的にはコレがすごくありがたい!)

デメリット

思いつきません。。。
強いて言うならインデントがあるくらい?

13
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10