2012年4月15日日曜日

[groovy]Immutableなクラス

@ImmutableアノテーションをクラスにつけてあげるとImmutableなクラスが実現できる。

※Immutableアノテーションは、groovy.langパッケージにもあるけど、非推奨になっているのでgroovy.transformの方をしようする。

Immutableなクラスの例

import groovy.transform.Immutable

@Immutable
class Hoge {
  String hoge
  int num
}

Immutableなクラスを変更しようとするとどうなるか?

Hogeクラスをインスタンス化し、hogeプロパティを変更してみます。
def hoge = new Hoge(hoge: "hoge", num: 100)
hoge.hoge = "変更"

実行してみると、ReadOnlyPropertyExceptionが発生し、クラスの状態が変更できないことがわかります。
Caught: groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: hoge for class: goovy.immutable.Hoge
groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: hoge for class: goovy.immutable.Hoge
 at goovy.immutable.Hoge.setProperty(Hoge.groovy)
 at goovy.immutable.main.run(main.groovy:6)

==演算子

Immutableなクラスにしてあげると、「==」演算子をオーバライドしてくれます。

お試しコード。
def hoge = new Hoge(hoge: "hoge", num: 100)

// immutableなオブジェクトは、「==」をオーバライドしてくれるから、
// 同じあたいかどうかになる
assert hoge == new Hoge(hoge: "hoge", num: 100)
assert hoge != new Hoge(hoge: "hoge", num: 101)

def mutableHoge = new MutableHoge(hoge: "hoge", num : 100)
// mutableなオブジェクトは、==がオーバライドされないので同一インスタンスかの比較
assert mutableHoge != new MutableHoge(hoge: "hoge", num : 100)


ImmutableだとtoStringまで実装される

Immutableなクラスだと、toStringまで追加されるようです。

Immutableでないと、「hoge = goovy.immutable.Hoge@6c0089ab」な感じになりますが、Immutableだと「hoge = goovy.immutable.Hoge(hoge:hoge, num:100)」なります。