2012-05-09 13 views
12

私は、rubyのすべてのクラスがメタクラスクラスのインスタンスであると理解します。そして、「通常の」オブジェクトは、これらのクラスのインスタンス(メタクラスクラスのインスタンス)です。ruby​​ metaclass confusion

しかし、私はクラスがオブジェクトのルートであり、クラスはそれ自身がクラスのインスタンス(インスタンスがクラスであるため、メタクラスと呼ばれます)であることを思い出しています。私はいくつかのブログでクラスクラスのメソッドnewのオーバーライドを見ました。

クラスはクラスとして動作しますが、そのインスタンスはクラスです。だから、我々は円を持っているようだ、それはクラスが好きに見えるクラスは、それ自身のインスタンスです。

私は明らかにここにポイントがありません。クラスクラスの起源は何ですか?

ここで私を混乱させています例です:

class Class 
    def new 
    #something 
    end 
end 

しかし、キーワードclassはClassクラスのインスタンスを意味します。それではどうやって動くの?

+4

'Class.class#=> Class' – Flexoid

+5

これはすべての方法で亀です! –

+0

[The class/object paradox confusion](http://stackoverflow.com/questions/7675774/the-class-object-paradox-confusion)も参照してください。 –

答えて

28

この作品

簡単操作を行います。そうでないと。とにかくルビーではない。

他のほとんどの言語と同様、単純に存在すると思われるいくつかのコアエンティティがあります。彼らは空から落ち、薄い空気の中に現れ、魔法のように現れる。 Rubyで

、それらの魔法の事のいくつかは、次のとおりです。

  • Objectは、スーパークラスを持っていませんが、あなたはありませんスーパークラスを持つクラスを定義することはできません、暗黙の直接のスーパークラスは常にObjectです。 [注:実装定義のスーパークラスObjectが存在する可能性がありますが、最終的にスーパークラスを持たないスーパークラスが存在します。]
  • Object
  • Class
  • (間接的 ObjectObject自体のインスタンスであることを意味する) Objectのサブクラスである、 Classのインスタンスである Class
  • Classのインスタンスである、ModuleのサブクラスでありますClass

これらはいずれもRubyで説明することはできません。

BasicObject,Object,ModuleおよびClassは、それらが循環依存性を有するため、同時に存在する必要があります。

この関係はRubyコードで表現できないという理由だけで、Ruby言語仕様ではそうでなければならないとは言えません。これを行う方法を理解するのは実装者次第です。結局のところ、Ruby実装には、プログラマが持っていないオブジェクトへのアクセスレベルがあります。

例えば、Rubyの実装では、最初にそのsuperclassポインタとnullに対するclassポインタの両方を設定し、BasicObjectを作成することができます。

その後、それはBasicObjectへのsuperclassポインタとnullへのclassのポインタを設定し、Objectを作成します。

次に、Objectに対するsuperclassポインタとnullに対するclassポインタを設定し、Moduleを作成します。

最後に、それはModuleへのsuperclassポインタとnullへのclassのポインタを設定し、Classを作成します。

今、私たちはClassを指すようにBasicObject年代、Object年代、Module年代、およびClassclassポインタを上書きすることができ、私たちは完了です。

これはシステム外から行うのは簡単ですが、内部から奇妙に見えます。

ただし、doが存在すると、それらの動作のほとんどを単純なRubyで実装することは完全に可能です。 Rubyのオープンクラスのおかげで、それらのクラスの非常にベアボーン版だけが必要です。あなたは後で欠けている機能を追加することができます。あなたの例では

class Classは、ランタイム環境によって私たちに与えられた既存クラスClassを、再開され、Classという名前の新しいクラスを作成していません。

だから、プレーンなRubyでClass#newのデフォルトの動作を説明するために完全に可能である:

class Class 
    def new(*args, &block) 
    obj = allocate # another magic thing that cannot be explained in Ruby 
    obj.initialize(*args, &block) 
    return obj 
    end 
end 

[注意:実際には、initializeはプライベートですので、あなたはアクセス制限を回避するためにobj.send(:initialize, *args, &block)を使用する必要があります。]

BTW:Class#allocateは、これらの魔法のものです。これはRubyのオブジェクト空間に新しい空のオブジェクトを割り当てます。これはRubyでは実行できないものです。したがって、Class#allocateは、ランタイムシステムによっても提供されなければならないものです。

+3

"BasicObject"のスーパークラスは 'BasicObject'なので、' 'BasicObject''のスーパークラスは' nil'です。 –

+2

@AndrewMarshall:1.9の新機能です。 1.8は 'BasicObject'を持たない' Object'しか持っていません。 –

+2

@HolgerJust Trueですが、1.8は寿命末期に近づきます。質問者が指定しない限り、私はRubyの最新バージョンを想定しています。 –

1

少し古いですが、this article by _whyが動作の理解に役立つかもしれません。あなたはPaolo PerrottaのMetaprogramming Rubyの件名をさらに深く知ることができます。

+0

どうしてパレルロが "メタクラス"という言葉を使うのとは関係ないのか?彼が話しているのは、シングルトンクラスか、より口語的には、固有クラスです。 – Chuck

2

はい、クラスはそれ自体のインスタンスです。これはModuleのサブクラスでもあり、Classのインスタンスでもあり、ModuleはClassのインスタンスでもあるObjectのサブクラスです。これはまったく循環していますが、これはライブラリの中ではなく、コア言語の一部です。 Rubyランタイム自体には、Rubyコードを書くときと同じ制限がありません。

私はクラスについて話すのに使われた "メタクラス"という言葉を聞いたことはありません。これはRubyにはあまり使われていませんが、それが正式に「オブジェクトのシングルトンクラス」と呼ばれるものと同義です。これはObject-Module-Classの三角形よりもはるかに混乱しやすいトピックです。どのように

+1

実際には、クラスは一般的な定義に従ってメタクラスと呼ばれることがあります。しかし、私は間違って多くのルビー主義者によって他のもののために使用された世界のメタクラスです。しかし、これらのメタクラスは一般的な定義によれば弱いメタクラスである。私がよく覚えているのは、しばしばルビのメタクラスと呼ばれるものは、クラスメソッドを保持するシングルトンです。私はそれについていくつかの記事を読んで、メタクラスという言葉が間違って使われていたと言って、この時点で彼らはレールチームを非難していました。みんな、ありがとう。 – Perello

2

「ツイスト」リンクによってメタ円形度が与えられています。これは、ルートの固有クラスからClassクラスまでの組み込みスーパークラスリンクです。これはeigenclassとスーパーリンクから誘導さ.classマップは、このマップを見て理解する

BasicObject.singleton_class.superclass == Class 

手がかりで表すことができる:オブジェクトxため、x.classx年代のスーパーチェーンの最初のクラスであります固有クラス。これはy.superclass(i)yni番目のスーパークラスx.eigenclass.superclass(n)クラスで最も小さいようであることを意味し、

eigenclasssingleton_class (即値の問題に対して耐性)の「概念的なエイリアス」である
x.class == x.eigenclass.superclass(n) 

で表すことができます。 。同様に、x.eigenclassのスーパークラス鎖の固有クラスはスキップされている(rb_class_realもMRIではリンクが間接的に–に実装されていることが明らかになった。「 iclasses」をスキップすると発生する)。 この結果、すべてのクラス(およびすべての固有クラス)のclassは常にClassクラスです。

画像はthis diagramで提供されています。

  • Smalltalkの

    メタクラス混乱は2つの主な発生源を有しています。 Smalltalk-80オブジェクトモデルには、Rubyオブジェクトモデルで修正された概念的な不一致が含まれています。さらに、Smalltalkの文献では、用語では弁証法を使用していますが、残念なことにRuby文献では十分に改善されていません。

  • メタクラスの定義。現在のところ、この定義ではメタクラスはクラスのクラスであると記載されています。しかし、いわゆる "暗黙のメタクラス"(RubyとSmalltalk-80の場合)の場合、より適切な定義は、メタオブジェクトのクラスとなります。