Effective Ruby 第五章 メタプログラミング まとめ その1
Effective Ruby 第四章 例外 まとめ - Memento memo. の続きです。
第五章 メタプログラミングについての前半部です。
- 作者: Peter J.Jones
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/19
- メディア: Kindle版
- この商品を含むブログ (4件) を見る
モジュール、クラスフックを使いこなす
- Rubyのイベント通知 -> フック関数の実行は、適切な名前のメソッドを書くだけで実行可能
- 定義できるフックは10種類
hookメソッド | タイミング |
---|---|
included | moduleがincludeされる |
extended | moduleがextendされる |
prepended | moduleがprependされる |
inherited | classが継承される |
method_added | method追加 |
method_removed | method削除 |
method_undefined | method定義解除 |
singleton_method_added | 特異method追加 |
singleton_method_removed | 特異method削除 |
singleton_method_undefined | 特異method定義解除 |
- 全てのフックメソッドは特異メソッドとして定義する
- method追加、削除、定義解除系のフックは引数としてメソッド名を受け取る。クラス名を知りたい場合はselfを使う。
- 全てのフックメソッドは自動的にprivateになる
- フックメソッドに関連する以下のメソッドはオーバーライドしてはならない。フックを使うこと。
- extend_object
- append_features
- prepend_features
module PreventInheritance class InheritanceError < StandardError; end def inherited(child_klass) raise(InheritanceError, "#{child_klass} cannot inherit from #{self}") end end ::Array.extend(PreventInheritance) class ChildArray < ::Array; end #=> ChildArray cannot inherit from Array (PreventInheritance::InheritanceError)
inherited
フックを使うとこんな感じの使い方になります。
クラスフックからはsuperを呼び出す
- hookは他のモジュールで定義されたhookの制御を完全に奪ってしまう場合がある。
- クラスフックメソッド内では必ず
super
を呼ぶのが行儀が良い。
method_missingではなくdefine_methodを使う
- method_missingを使ってはいけない理由
- パフォーマンス面でコストがかかる
- エラーメッセージが分かりにくくなる
respond_to?
等のイントロスペクションメソッドが使えなくなる。
- method_missingで本来やりたいことの大半はproxy, decorator patternの実装だが、これらはdefine_methodで代替可能
- proxyの実装
class HashProxy Hash.public_instance_methods(false).each do |name| define_method(name) do |*args, &block| @hash.send(name, *args, &block) end end def initialize @hash = {} end end
- decoratorの実装
require('Logger') class AuditDecorator def initialize(object) @object = object @logger = Logger.new($stdout) @object.public_methods.each do |name| define_singleton_method(name) do |*args, &block| @logger.info("calling '#{name}' on #{@object.inspect}") @object.send(name, *args, &block) end end end end
上記例の用に、オブジェクトの場合は define_singleton_method
で特異メソッドを定義できます。
- どうしても
method_missing
を避けられない場合はrespond_to_missing?
を併用する。 respond_to_missing?
はrepond_to?
がメソッドを見つけられなかった場合の最後のチャンスをプログラマに委ねる。
evalの多様な変種間の違いを把握する
eval
,instance_eval
,class_eval
で直接文字列を評価するのは避ける。- 代わりに
class_exec
,instance_exec
とブロックを使うと変数のvalidation等が行えるようになる。
参考
細かいところはメタプログラミングRubyを読む必要がありそうですね。
- 作者: Paolo Perrotta,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/10/10
- メディア: 大型本
- この商品を含むブログ (2件) を見る
続きます。