Closure 型のプロパティを使って
class Main{ def closure = { println 'This is closure.' } } def main = new Main() main.closure()
とやると普通に実行できて「This is closure.」と表示されます。 Groovy ではオブジェクトに対して () を付けると call() メソッドの呼び出しになるはずなので、以下のようなコードが動くかなぁと思ったんですが
class Main{ def callable = new MyCallable() } class MyCallable{ def call() { println 'This is Callable.' } } def main = new Main() main.callable()
実際に実行してみると例外が投げられました(Groovy 2.0.1)。 callable() メソッドがないっていう例外のようです。 ちなみに、同じ Main クラス、MyCallable クラスを用いて
def main = new Main() // 一旦、プロパティを変数に格納 def callable = main.callable callable() // 「This is Callable」と表示 // main.callable を先に評価させる (main.callable)() // 「This is Callable」と表示
とすると、思ったように表示されます。
まぁ、メソッドとプロパティに対する call() メソッドをキチンと使い分ければいいだけですが、敢えてあいまいな使い方をできるようにする方法を見ていきましょう。 大雑把には次の2つです(他にもあるかも知れませんが):
- Main クラスの methodMissing() メソッドを実装する
- 自作の Closure クラスを作製する
Main クラスの methodMissing() メソッドを実装する
まずは Groovy のメタプログラミングによる方法。 この方法には、Main クラス自体をいじるものと、実行時に MetaClass をいじるものがありますが、どちらも同じようなものです。
まずは Main クラスをいじる方法:
class Main{ def callable = new MyCallable() // メソッドがない場合は、プロパティを取得して call() メソッドを呼び出す def methodMissing(String name, args){ this."$name".call() } } class MyCallable{ def call() { // cannot be doCall() println 'This is Callable.' } } def main = new Main() main.callable() // 「This is Callable.」と表示
常に Main クラスのコードが書き換えられるとは限らないので、MetaClass を使って以下のように実行時に methodMissing() メソッドを追加する方が融通の利く方法かと思います:
class Main{ def callable = new MyCallable() } class MyCallable{ def call() { // cannot be doCall() println 'This is Callable.' } } // Main クラスに methodMissing() メソッドを追加 Main.metaClass.methodMissing = { String name, args -> delegate."$name".call() } def main = new Main() main.callable() // 「This is Callable.」と表示
言うまでもないかも知れませんが、Main クラスをインスタンス化する前にメタクラスをいじりましょう(試してるときにちょっとハマったので)。
自作の Closure クラスを作製する
次は自作の Closure クラス(のサブクラス)を作製する方法。 一番、普通っぽいプログラミングって感じですが、Closure オブジェクトのインスタンス生成って重いのか軽いのか不安・・・
class Main{ def myClosure = new MyClosure() } class MyClosure extends Closure{ MyClosure() { super(null) } @Override def doCall() { // cannot be call() println 'This is my closure.' } } def main = new Main() main.myClosure() // 「This is my closure.」と表示
Closure クラスのサブクラスでは doCall() メソッドをオーバライドする必要があります。 call() メソッドを実装していると、実行時に「doCall() メソッドがない」という例外が投げられます。
まぁ、これらの方法を多用するとコードのメンテナンスが大変になりそうだけど、メソッドの代わりに Closure 型のプロパティを定義するってのは Grails とか Griffon で普通に使われてるかと思うので、自分で定義したクラスについても出来るようになってほしいなぁ。
- 作者: 関谷和愛,上原潤二,須江信洋,中野靖治
- 出版社/メーカー: 技術評論社
- 発売日: 2011/07/06
- メディア: 単行本(ソフトカバー)
- 購入: 6人 クリック: 392回
- この商品を含むブログ (152件) を見る
- 作者: Dierk Konig,Andrew Glover,Paul King,Guillaume Laforge,Jon Skeet,杉浦孝,櫻井正樹,須江信洋,関谷和愛,佐野徹郎,寺沢尚史
- 出版社/メーカー: 毎日コミュニケーションズ
- 発売日: 2008/09/27
- メディア: 単行本(ソフトカバー)
- 購入: 5人 クリック: 146回
- この商品を含むブログ (121件) を見る