Foo = Module.new
class MyClass
include Foo
end
モジュールがクラスに含まれると、匿名プロキシ クラスが作成され、MyClass のスーパークラスとして設定されます。
MyClass.ancestors => [MyClass, Foo, ...]
しかし、モジュールが拡張されると内部で何が起こるのでしょうか? Ruby はこれをどのように処理しますか?
Foo = Module.new
class MyClass
include Foo
end
モジュールがクラスに含まれると、匿名プロキシ クラスが作成され、MyClass のスーパークラスとして設定されます。
MyClass.ancestors => [MyClass, Foo, ...]
しかし、モジュールが拡張されると内部で何が起こるのでしょうか? Ruby はこれをどのように処理しますか?
あなたが尋ねているのはObject#extend
したがってextend
、 を使用すると、任意のモジュールのメソッドをそのオブジェクトに含めることができます。たとえば、HelperModule というモジュールがあります。
module HelperModule
def foo
puts "from module helper"
end
end
obj = Object.new
obj.extend HelperModule
obj.foo # => "from module helper"
class MyClass
extend HelperModule
end
MyClass.foo # => "from module helper"
内部的には、 Metaprogramming Rubyによると:
Object#extend() は、レシーバーの固有クラスにモジュールを含める単純なショートカットです。
ruby のメソッド call の簡単な説明:
obj
|
| class
| superclass superclass
---> ObjectClass --------------> SuperClass1 --------------> SuperClass2 ....
固有クラスとメソッド呼び出しパスについての詳細な説明は、このすばらしい本Metaprogramming Rubyを参照してください。
ありがとう
モジュールが Ruby で拡張されると、内部で何が起こりますか?
モジュールM
がクラスにインクルードされると、メソッド テーブル ポインタが のメソッド テーブルを指すようC
に、匿名プロキシ クラス(インクルード クラス⟦M′⟧
と呼ばれる) が作成されます。(定数テーブルとモジュール変数についても同じです。)のスーパークラスは のスーパークラスに設定され、 のスーパークラスは に設定されます。M
⟦M′⟧
C
C
⟦M′⟧
また、M
他のモジュールが含まれる場合、プロセスは再帰的に適用されます。
実際、これはデフォルトの動作です。実際に起こるのはのinclude
呼び出しであり、そのメソッドをオーバーライドすることM.append_features(C)
ですべての動作をカスタマイズできます。
Rubiniusのソース コードはModule#append_features
非常に読みやすいと思います。
obj.extend SomeModule
と同じですobj.eigenclass.include SomeModule
(注: これは単なる疑似コードですが、アイデアは得られます...)。