うさぎ組

ソフトウェア開発、チームによる製品開発、アジャイル、ソフトウェアテスト

Re:GroovyのPowerAssertさんをいじめようとしてみた

今さらというか、下書きが残っていたので公開。

はじめに

まずは
id:irof (@) さんの【GroovyのPowerAssertさんをいじめようとしてみた - 日々常々】を読んでください。
今回はこのPowerAssertという素晴らしい機能についての説明です。

PowerAssertをぶっこわしたい

結論から言うと、無理です。
PowerAssertが表示するときは対象のオブジェクトに対して2つのメソッドをコールするパターンがあります。

  1. toString()をコールする
  2. getClass().getName()をコールする。


まずtoString()をコールしますが、例外が発生した場合はキャッチされ、getClass().getName()がコールされます。
そして、getClass()はfinalメソッドであるため、基本的にはオーバーライドできません。(無理やりfinalを上書きもできた気がするが、うろ覚え。


また、toString()がnull、空文字の場合でも同じようにgetClass().getName()がコールされます。
なので、「とりあえず空文字でも実装すればいいよね!」とかやっていると動きません。
空文字の場合でもうまく表示されるのは、String, StringBuffer, StringBuilderのみです。

toString()とかequals()とかだるい

そこで、@Canonicalですよ。
Groovyではclass宣言に@Canonicalというアノテーションをつければ、コンパイルタイムに

  1. toString()
  2. equals()
  3. 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つけておけばいい。