【Ruby】include extend の考え方の違いって?
以前、
何でModuleモジュールのプライベートメソッドが任意のクラスで見えるか
は分かったけれど、
どうしてinclude extend 二通りの継承方法があるのか
がまだ分からない。
「そういうものだから」といわれたらそれまでだけど
わざわざextend というルールを採用した理由は?
そこにはどんな思想があるのか。
調べてみよう。
include,extend の違い
前に理解したのは、
include インスタンスメソッドとして取り込む
extend クラスメソッドとして取り込む
このレベルまで。
でも考えてみたら、
Moduleでもクラスメソッドを定義できるし
module_function メソッドも存在する。
いろんな機能がごっちゃになって整理できていない。
順に追ってみよう。
extendはオブジェクトへの追加
公式ガイドをみてみると
Module#include は、 クラス(のインスタンス)に機能を追加しますが、 extend は、ある特定のオブジェクトだけに モジュールの機能を追加 したいときに使用します。
ふむ。
extend(*modules) 引数で指定したモジュールのインスタンスメソッドを self の特異 メソッドとして追加します。
module Foo def a 'ok Foo' end end obj = Object.new obj.extend Foo p obj.a #=> "ok Foo"
なるほど。
あくまでもレシーバとなるオブジェクトに性質を注入している。
クラスの地の文も、ただの文だから、
通常のこの書き方は↓
class Aaa extend Momo end
レシーバを略さずに書くと↓
class Aaa self.extend Momo end
つまり、Aaaクラスオブジェクトに性質を注入している。
なるほど。
だからextendで取り込んだモジュールのメソッドは
クラスメソッドになるんだ。
Aaaクラスオブジェクトは
Aaaメタクラスのインスタンスであると捉えると、
Aaaクラスへのextendは、
Aaaメタクラスに対する Module#includeと言い替えることもできる。
クラスに対してはincludeを使う オブジェクトに対してはextendを使う
これがお勧めの使い方のようだ。
考え方が違うから、この2種類が存在するのか。
なるほど。