LoginSignup
4
3

More than 5 years have passed since last update.

Groovyでコンパイル時に型チェック

Posted at

今更ですが、Groovyでコンパイル時に型をチェックするする方法をまとめました。

import groovy.transform.TypeChecked
import groovy.transform.CompileStatic

/**
 * コンパイル時点でエラーが出れば、態々実行してテストする必要がなくなるのは自明。
 * 例えば下記のreturnCheck()メソッドの場合、ifの両方の条件を通るテストをしないと、
 * 意図していない型の値が返されるというバグが分からない。
 * (returnCheck()場合はIntegerを返す筈なのにStringが帰えされるバグがある)
 *
 * @TypeCheckedはコンパイル時に型をチェックするので、それが出来ない動的な機能は基本的に使えない。
 * なお、コンパイル時点でチェックするのみで、生成されるバイトコードは@TypeCheckedが無いものと同じ。
 * @CompileStaticを使うと、動的な機能が含まれないバイトコードになるため、基本的に実行の高速化・ファイル容量の減少が期待できる(はず)
 */

//@TypeChecked    // コンパイル時にチェックするだけ。
@CompileStatic    // コンパイル時にチェックし、生成するバイトコードも変化する(実行速度の向上)。
class Hoge  {

    def static main(args) {
        // 存在しないメソッド・変数を実行する。
        // これがコンパイルエラーに出来る。
        unknownMethod()
    }

    // Integer型の戻り値のはずなのに、Stringが帰る可能性がある。
    // これがコンパイルエラーにできる。
    Integer returnCheck(b) {
        if(b) {
            1
        } else {
            "string"
        }
    }

    // 引数aの型はStringなのに、Integer型のbに変数を代入している。
    // メソッド引数でなくとも、普通の代入でも同様。
    // これがコンパイルエラーに出来る
    // なお、実行時にDate以外の値を渡すと、実行時例外となる。
    def assignmentCheck(String a){
        Integer b = a
        Integer c = new String()
    }

    // 別のクラスのメソッドを呼ぶ際に、誤った型を渡す。
    // これがコンパイルエラーにできる。
    // "呼び出す側"に@TypeCheckedが宣言されている必要がある。
    // 当然Mock#add()の引数が型付で宣言されている必要がある。
    def callOther(){
        def mock = new Mock()
        mock.add(1,"2")
    }
}

class Mock{
    def add(Integer a, Integer b){
        a + b
    }
}
4
3
0

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
4
3