2017-07-13 13 views
2

私の理解では、モジュールがクラスに含まれると、モジュールのコピーが作成され、包含クラスとそのスーパークラスの間に置かれます。 私はRuby Under a MicroscopeによってPat Shaughnessyによって引用します。あなたは以下のことをしているとします含まれているモジュールへの参照を取得する

module Professor 
end 
class Mathematician < Person 
    include Professor 
end 

を我々は上記のコードを実行すると、RubyはProfessorモジュールのRClass構造体のコピーを作成し、Mathematicianのための新たなスーパークラスとしてそれを使用しています。 RubyのCソースコードは、を含むとしてこのモジュールのコピーを参照しています。 Professorの新しいコピーのスーパークラスは、元のスーパークラスMathematicianに設定され、スーパークラスまたは祖先チェーンは保持されます。

クラスを含むリファレンスはですか?たとえば、Objectクラスに含まれるKernelモジュールへの参照を取得したいとします。

+0

あなたの意図をさらに明確にするための例を示してください。 –

+0

なぜ 'module kernel 'を再オープンすれば十分ではないでしょうか? –

+1

さて、[モジュール#included_modules](http://ruby-doc.org/core-2.4.0/Module.html#method-i-included_modules): 'モジュールM;終わり;モジュールN;終わり;クラスC; Mを含む; Nを含む;終わり; C.included_modules#=> [N、M、Kernel] '。それはあなたが探しているものですか? –

答えて

1

サンプルでこれを見てみましょう:でもそれを指定せずに、FooObject(およびObjectを拡張し、ため

module Bar 
end 

class Foo 
    include Bar 
end 

p Foo.ancestors 
p Foo.included_modules 

これは

[Foo, Bar, Object, Kernel, BasicObject] 
[Bar, Kernel] 

ObjectBasicObjectを出力しますが、先祖階層にありますRuby 1.9+以来、少なくとも「BasicObject」を拡張しています(BasicObjectが導入されました)。 Foo直接Barを含み、ObjectKernelを含むため

BarKernelがモジュールに含まれています。

ただし、Moduleはコピーされません。メソッドを参照するときに参照され、使用されます。

あなたがここにいくつかの詳細を見つけることができます。​​

+0

編集した質問文をご覧ください。 –

3

私の理解では、モジュールがクラスに含まれている場合、モジュールの コピーが作られ、などのクラスとその の間に挟まれ、ということですスーパークラス。

ルビーの観点からは、コピーは作成されません。先祖に参照が追加され、それがそれです。

質問に記載されている動作("Ruby under a microscope"から抽出)は、おそらくCRubyに固有のものです。内部的には、Rubyモジュールは変更されたRClassとして保存され、モジュールが含まれるとコピーが作成されます。たとえば、Rubiniusのようには見えません。私はまた、コピーされた内部のRClassに、RubyのModuleを参照してアクセスすることはできないと考えています。

あなたはRubyの動作をこのように確認することができます。

module M 
    def copy_or_reference? 
    puts "copy!" 
    end 
end 

class A 
    include M 
end 

class B 
    include M 
end 

m2 = A.included_modules.first 
m2.send(:define_method, :copy_or_reference?) { puts "reference!" } 

B.new.copy_or_reference? 
#=> reference! 

我々はAの祖先からMモジュールを抽出します。この祖先モジュールのcopy_or_reference?メソッドを再定義します。元のMモジュールのコピーである場合、Bインスタンスから呼び出されたM#copy_or_reference?インスタンスは、依然として"copy!"を返します。

含まれるモジュールを取得するには、あなたも使用できます。古いバージョンで

A.ancestors.grep_v(Class) 
のRuby 2.3以降で

または

A.ancestors.reject{ |o| o.is_a?(Class) } 

を。

さらに詳しい情報が必要な場合は、@JörgWMittagにpingを試みることができます。

+1

これは実装に依存するかもしれませんが、MRIではモジュールがコピーされます(私の編集したテキストを参照してください)。コードが動作する理由は、コピーと元の両方が同じ関数テーブルへの参照を保持しているためです。私は実装に依存しているかどうかはおそらくコピーへの参照を取得する方法はないと思う。 –

+1

@OmarKhan:あなたが書いたことを正確に言及するために私の答えを更新しようとしていた。 "Ruby under a microscope"はすばらしい本ですが、必ずしも従うのは簡単ではありません。 –

+0

私は 'grep_v'について知っていましたが、それが使われたことは一度もありませんでした。 –

関連する問題