Re:GroovyのPowerAssertさんをいじめようとしてみた
今さらというか、下書きが残っていたので公開。
はじめに
まずは
id:irof (@irof) さんの【GroovyのPowerAssertさんをいじめようとしてみた - 日々常々】を読んでください。
今回はこのPowerAssertという素晴らしい機能についての説明です。
PowerAssertをぶっこわしたい
結論から言うと、無理です。
PowerAssertが表示するときは対象のオブジェクトに対して2つのメソッドをコールするパターンがあります。
- toString()をコールする
- getClass().getName()をコールする。
まずtoString()をコールしますが、例外が発生した場合はキャッチされ、getClass().getName()がコールされます。
そして、getClass()はfinalメソッドであるため、基本的にはオーバーライドできません。(無理やりfinalを上書きもできた気がするが、うろ覚え。
また、toString()がnull、空文字の場合でも同じようにgetClass().getName()がコールされます。
なので、「とりあえず空文字でも実装すればいいよね!」とかやっていると動きません。
空文字の場合でもうまく表示されるのは、String, StringBuffer, StringBuilderのみです。
toString()とかequals()とかだるい
そこで、@Canonicalですよ。
Groovyではclass宣言に@Canonicalというアノテーションをつければ、コンパイルタイムに
- toString()
- equals()
- hashCode()
が自動で生成され、Tupleベースなコンストラクタも追加されます。
これは、Groovyデフォルトのnew Hoge(a:"value1", b:"value2")だけではなく、new Hoge("value1", "value2")ができるということです。
さらっというと、@Canonicalは@ToString, @EqualsAndHashCode, @TupleConstructorを追加するのと同義です。
ちなみに@ToStringは@ToString(includeNames = true, includeFields = true)といった指定もでき、@Canonicalを指定したときにも次のように指定することで、有効になります。
import groovy.transform.* @Canonical @ToString(includeNames = true, includeFields = true) class Foo{ String a; int b; }
まとめ
とりあえず、@Canonicalつけておけばいい。