Rubyはattr_accessorとか書くとプロパティが作れるわけだが、これはインスタンス変数を読み書きするだけ。それ以上の動作をさせたい場合は自分でメソッドを定義する必要がある。
しかし名前が違うだけで処理内容が同じプロパティが沢山あったら超面倒くさい。例えば…
class Test def initialize @hash = Hash.new end def hoge; @hash["hoge"]; end def fuga; @hash["fuga"]; end def piyo; @hash["piyo"]; end def hoge=(val); @hash["hoge"]=val; end def fuga=(val); @hash["fuga"]=val; end def piyo=(val); @hash["piyo"]=val; end end
この程度ならば何とかなるが、処理が複雑になったり数がもっと増えたらやってられない。何か良い方法がありそうな気がするのだが見つからなかったので、Module#define_methodを使って何とかしてみた。
module Mod def define_accessors(*args) args.each do |attr| define_method(attr) { reader(attr) } define_method((attr.to_s+"=").to_sym) { |value| writer(attr, value)} end end end class Test extend Mod define_accessors :hoge, :fuga, :piyo def initialize @hash = Hash.new end def reader(name) @hash[name] end def writer(name, value) @hash[name] = value end end test = Test.new test.hoge = "a" test.fuga = "b" p test.hoge => "a" p test.fuga => "b"
define_methodはModuleの中でしか呼べないので適当なモジュールを作ってextendするという方法をとる。define_accessorsをModuleクラスに追加しても良いが標準ライブラリはあんまり弄りたくない。
class Module def define_accessors(*args) args.each do |attr| define_method(attr) { reader(attr) } define_method((attr.to_s+"=").to_sym) { |value| writer(attr, value)} end end end class Test define_accessors :hoge, :fuga, :piyo def initialize @hash = Hash.new end def reader(name) @hash[name] end def writer(name, value) @hash[name] = value end end
もっと上手い方法がないかなー、とゆうかRubyならば標準機能にあってもおかしくなさそうな気がするんだけど…
あと、コード量増えてんじゃん!というツッコミはなしの方向でお願いします。