意図しないメソッドの上書きを防ぐテクニック
Rubyには意図しないメソッドの上書きを防止する方法があります。このテクニックは例えば、既にあるクラスに独自拡張を加えるときなどに有効です。既に定義されているクラスをAとし(Aが例えばStringの場合では既に定義されています。Aのままの場合は、既にクラスが定義されているわけではありませんが、Rubyスクリプトとしては間違いではありません)、独自拡張したAのメソッドをa_methodとします。
#!/usr/local/bin/ruby #ファイル名:extend_class.rb class Module def check_method(method) if method_defined?(method) $stderr.puts "Warning:#{self}##{method} already exists" else yield end end end class A check_method("a_method") do def a_method; end end end
このとき、このファイルを間接的にrequireするようなスクリプトはAにa_methodが追加されていることを知りません。もしかしたらこちらのスクリプトでもa_methodが定義されている可能性があります。このようなとき、既に定義されていると、警告を出すと誤動作の原因をすぐに特定することができます。上のファイルextend_class.rbに試しにクラスBを次のようにたして
class B < A check_method("a_method") do def a_method; end end end
実行してみると、"Warning:B#a_method already exists"と表示される。
このテクニックはRake(0.8.7)で使われている。
###################################################################### # Rake extensions to Module. # class Module # Check for an existing method in the current class before extending. IF # the method already exists, then a warning is printed and the extension is # not added. Otherwise the block is yielded and any definitions in the # block will take effect. # # Usage: # # class String # rake_extension("xyz") do # def xyz # ... # end # end # end # def rake_extension(method) if method_defined?(method) $stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists" else yield end end end # module Module