前回の include は比較的どうでもいい話。
includeは、クラスに対してモジュールのメソッドを追加するので、そのクラスのインスタンスすべてがモジュールのメソッドを使えるようになる。JavaScriptで言えばprototypeにメソッドをセットするようなもの。一方、extendでは、特定のインスタンスに対してモジュールのメソッドを追加する。
module Fuga def execute; puts "fuga"; end end class Hoge end hoge1 = Hoge.new hoge1.extend Fuga hoge1.execute # "fuga"と表示 hoge2 = Hoge.new hoge2.execute # NoMethodError
で、extendって何に使うんだという話だが、正直よくわからん。
initialize時に引数によってextendするモジュールのインスタンスの動作を変更してファクトリ不要のテンプレメソッドパターンとシャレこんでみたりする。
class Hoge def initialize(sym = nil) case sym when :a self.extend A when :b self.extend B end end def run execute end def execute puts "default" end module A def execute puts "extended A" end end module B def execute puts "extended B" end end end Hoge.new.run Hoge.new(:a).run Hoge.new(:b).run
だるいので引数にモジュール自体を渡してみる。
class Hoge def initialize(mod = nil) if not mod.nil? then self.extend mod end end # ... 同じなので略 end Hoge.new.run Hoge.new(Hoge::A).run Hoge.new(Hoge::B).run
どことなくprototypeベース的な香りのするmoduleだが、こんな感じで色々遊べそう。継承に頼らずともポリモーフィズムできるのが動的オブジェクト指向の良いところ。それと、extendすると元から持っている同名のメソッドが上書きされるので注意。