groovy1.6のdefineメソッドについて

2019-05-08Groovy

metaClass.defineが凄い! より。

Groovy1.6から、 metaClass.define という記述で、既存クラスにメソッドを追加出きるそうです。試しにjavaでは継承不可能なStringクラスにメソッドを追加してみる。

String.metaClass.define {
    toFile {
        new File(delegate)
    }

    half {
        def end = Math.round(delegate.size() / 2) - 1
        delegate[0..end]
    }
}

def path = "/home/genzou"
println path.toFile()
println path.half()

def path2 = "home_genzou_bin"
path2.metaClass.define {
    camelize {
        delegate.toLowerCase().replaceAll("_[^_]") { it[1].toUpperCase() }
    }
}
println path2.half()
println path2.camelize()
// これはエラー
// println path.camelize()
  • クラス.metaClassに対して指定したメソッド(クロージャ?)は当然すべてのインスタンスに適用された。
  • インスタンス.metaClassに対して指定したメソッド(クロージャ?)は、そのインスタンスにしか適用されない。

確かにこれは定義がしやすい。通常のclass定義の構造によく似ている。

define内で定義するメソッドに引数が必要な場合には、以下のように定義する。

File.metaClass.define {
    // メソッドのように定義
    searchExt(ext) {
        delegate.listFiles().findAll {
            it.name =~ /^.+.${ext}$/
        }
    }
    // クロージャのように定義
    searchName { name ->
        delegate.listFiles().findAll {
            it.name == name
        }
    }
}

new File("/home/genzou").searchExt("groovy").each {
    println it
}

2019-05-08Groovy