extendとincludeの違いについて
ruby2.0
moduleを取り込むのにinculudeとextendがあって
あ・れ・はなんなんじゃ なんじゃ なんじゃにん(ry となったので調べてみた。
違いは継承ツリーのどこに差し込まれるかという話っぽい。
includeは(includeした)元のクラスの上に差し込まれる。
extendは(extendした)元のオブジェクトの特異クラスの上に差し込まれる。
それとincludeとextendは並べがちだけど定義されてる場所が違う。
[1] pry(main)> String.method(:extend) => #<Method: Class(Kernel)#extend> [2] pry(main)> String.method(:include) => #<Method: Class(Module)#include>
include
module IncludeModule def unko :unko end end class Foo include IncludeModule end Foo.ancestors # [Foo, IncludeModule, Object, Kernel, BasicObject]
Fooクラスの上にIncludeModuleで現れていて親クラスっぽい感じで使えるようになる。
extend
extendでmoduleを取り込むと特異クラスの継承ツリーに現れる。
また、取り込み先の上に差し込まれる。
module ExtendModule def hello :hello_hoge end end class Foo extend ExtendModule end p Foo.singleton_class.ancestors # [ExtendModule, Class, Module, Object, Kernel, BasicObject] p Foo.hello # :hello_hoge # ancestorsメソッドで特異クラス自身が見えないのはruby2.0以前の仕様らしく、2.1から表示されるようになるとのこと。
特異クラスの上に挿されるのでクラスメソッドととして呼べている。
また、extendは特異クラスに取り込まれるということでインスタンスに対しても使える。
p foo = Foo.new foo.extend(ExtendModule) foo.hello # :hello_hoge
まとめ
全然違う