イベントハンドラみたいなのをRubyで書きたい
C#で言うところのEventHandlerみたいな奴がRubyで欲しくなったので勉強してみた。
#!/usr/bin/ruby -Ku # -*- coding: utf-8 -*- # 呼ばれる側 その1 class Class1 def class1_print puts " called:Class1.class1_print()" end def class1_print_with_arg(arg) puts " called:Class1.class1_print_with_arg() arg is: #{arg}" end end # 呼ばれる側 その2 class Class2 def class2_print puts " called:Class2.class1_print()" end def class2_print_with_arg(arg) puts " called:Class2.class2_print_with_arg() arg is: #{arg}" end end # EventHandlerみたいなモノ class Caller # Methodオブジェクトを格納する配列 @methods = nil # コンストラクタ def initialize @methods = Array.new end # Methodオブジェクト配列に関数を登録 def register_func(method) @methods << method end # caller += hoge と書けるように演算子オーバーロード def +(method) register_func(method) return self end # 登録した関数を削除 def unregister_func(method) @methods.delete(method) end # caller -= hoge と書けるように演算子オーバーロード def -(method) unregister_func(method) return self end # 現在登録されている関数を全て呼び出す def call_them_all @methods.each do |method| method.call end end # 引数を渡して全て呼び出す def call_them_all_with_arg(arg) @methods.each{|method| method.call(arg)} end end class1 = Class1.new class2 = Class2.new caller = Caller.new puts "・何も登録していない状態でのCaller呼び出し" caller.call_them_all puts "→何も呼ばれない" puts puts "・class1_printを登録" caller += class1.method(:class1_print) # caller.register_func( class1.method(:class1_print) ) と同じ puts "Caller呼び出し" caller.call_them_all puts "→class1_printが呼ばれる" puts puts "・class2_printを登録" caller += class2.method(:class2_print) puts "Caller呼び出し" caller.call_them_all puts "→class1_print、class2_printが呼ばれる" puts puts "・class1_printを削除" caller -= class1.method(:class1_print) puts "Caller呼び出し" caller.call_them_all puts "→class2_printが呼ばれる" puts puts "・Callerを初期化" caller = Caller.new puts puts "・class1_print_with_arg class2_print_with_argを登録" caller += class1.method(:class1_print_with_arg) caller += class2.method(:class2_print_with_arg) caller.call_them_all_with_arg("Argument string.") puts "→class1_print_with_arg、class2_print_with_argが呼ばれる"
実行結果:
・何も登録していない状態でのCaller呼び出し →何も呼ばれない ・class1_printを登録 Caller呼び出し called:Class1.class1_print() →class1_printが呼ばれる ・class2_printを登録 Caller呼び出し called:Class1.class1_print() called:Class2.class1_print() →class1_print、class2_printが呼ばれる ・class1_printを削除 Caller呼び出し called:Class2.class1_print() →class2_printが呼ばれる ・Callerを初期化 ・class1_print_with_arg class2_print_with_argを登録 called:Class1.class1_print_with_arg() arg is: Argument string. called:Class2.class2_print_with_arg() arg is: Argument string. →class1_print_with_arg、class2_print_with_argが呼ばれる
とりあえずそれっぽく動いた。関数っていう呼び方が正しくないのはご愛敬。
クラスメソッドを取得するのに、some_instance.method(:method_name)という形式を取るのがちょっとモニョるけど、RubyらしいといえばRubyらしい…かな?
# っていうか誰か作ってるんじゃないかなこういうの…