2008-12-18 (Thu) [長年日記]
▲ Re: はじめてのSwing on JRubyその弐
id:xibbarさんのところでJRubyチュートリアルっぽいことをしているので便乗してみます。
最後のSimpleGui1Bクラスは次のように書くと多少Rubyっぽく見えるかもしれません。
require 'java' import javax.swing.JFrame import javax.swing.JButton class SimpleGui1B def initialize frame = JFrame.new button = JButton.new("click me") frame.default_close_operation = JFrame::EXIT_ON_CLOSE frame.content_pane.add(button) frame.setSize(300,300) frame.visible = true button.add_action_listener java.awt.event.ActionListener.impl { |method, e| e.source.text = "I've been clicked!" } end end SimpleGui1B.new
JRubyの場合、Javaインターフェースを直接実装したクラスを作らなくてもRubyのブロックを渡して実装クラスとすることができます。この場合、第1ブロック引数にはメソッド名が文字列で渡されます*1。第2のブロック引数にはイベント発生時に渡される情報(この場合java.awt.event.ActionListenerを実装したインスタンス)が渡されます。
Swingのイベントハンドラのようにメソッドがひとつしかない単純なインターフェースを持ったクラスがたくさん必要なプログラミングでは特に、Rubyの強力なブロック渡しを活用することで簡潔に書けますね。
またブロックはコンテキストを保持するため@buttonをインスタンス変数にする必要が無くなるのもポイントでしょうか。
追記12/19: @tom_eneboからインターフェースのimplメソッドは使わなくてよいと教えてもらったので、その場合のソースも書いておきます。より短くなりました。
require 'java' import javax.swing.JFrame import javax.swing.JButton class SimpleGui1B def initialize frame = JFrame.new button = JButton.new("click me") frame.default_close_operation = JFrame::EXIT_ON_CLOSE frame.content_pane.add(button) frame.setSize(300,300) frame.visible = true button.add_action_listener { |e| e.source.text = "I've been clicked!" } end end SimpleGui1B.new
*1 メソッド名をキーに処理をディスパッチするのに使えます。
なかなかRuby的に書ける部分がわかんなかったりして、<br>それがハードルだったりしますよね。<br>JRubyの本無いのかしらなんて思ったけど、ないし。<br>このシリーズ、もうちょっと続けていくので、<br>できればフォローしていただけたら助かります。