- ベストアンサー
Ruby 特異メソッドのnewが先に実行?
- Rubyのインスタンス生成について質問があります。
- Hoge = Class.new() の場合、Hogeクラスには特異メソッドのみを定義でき、通常のインスタンスメソッドは定義できません。
- hoge = Class.new() の場合は、クラスオブジェクトではなくただのインスタンスとなります。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
Class.newにおけるnewは、マニュアルにある通り特異メソッドから検索されますので、Classクラスの特異メソッドです。Class.newでできるインスタンスは、無名のクラスです。代入先で挙動が変わることはないです。 クラス定義で用いられる次の構文は、 class Hoge end 以下の3つの作業をしています。 1.Classクラスのインスタンスを生成 2.そのインスタンスにHogeという名前を付ける 3.Hogeという定数の参照先をこのインスタンスにする Class.newは、1の作業のみをしています。 Class.newでできた無名クラスは、定数に代入される(参照される)とその定数名と同じ名前が付けられます。上述した作業2→3の逆順の3→2をしていることになります。名前がない状態で表示すると、普通のインスタンスと同様に生成元のクラス(この場合Class)とそれのアドレスが表示されます。 hoge = Class.new # hogeという変数が無名クラスを参照 p hoge # 無名クラスなので生成元クラスとアドレスを表示 Hoge = hoge # Hogeという定数が無名クラスを参照 p hoge # この時点ではHogeという定数が無名クラスを参照しているので、この無名クラスにHogeという名前が付けられる >No.2、notnotさん マニュアルの以下の文はその通りだと思います。 >名前のないクラスは、最初に名前を求める際に代入されている定数名を検索し、 >見つかった定数名をクラス名とします。 名前が求められた際、定数が格納されているハッシュテーブルのスロットを上から順に見ていき、最初に見つかった定数の名前をそのクラスの名前にしているのだと思います。検索順序は、Object.constantsで表示されるものと多分同じだと思います。 Ruby1.9の場合はハッシュに順番を付けたので、最初に代入した定数が先に見つかりそういう結果になったのだと思います。
その他の回答 (3)
- ryu_chan
- ベストアンサー率37% (69/186)
Class.newだけでクラスオブジェクトが作られます。 クラスとは、Classクラスのインスタンスであり、そのインスタンスのことをクラスオブジェクトと呼びます。名称が複数あるだけで、とりあえず全て同じものを指していると思って差支えないと思います。 クラス ≒ Classクラスのインスタンス ≒ クラスオブジェクト Hogeクラス ≒ Hogeという名前のClassクラスのインスタンス ≒ Hogeという名前のクラスオブジェクト hoge = Class.new();(1) これは、まずClass.newで(無名の)クラスオブジェクトが作られます。そして、hogeという変数がそのクラスオブジェクトを参照するようにしています(hogeという変数にクラスオブジェクトのリファレンス(アドレス)を代入している)。 Hoge = hoge;(2) これは、Hogeという定数に先ほど作られたクラスオブジェクトを参照するようにしています。無名だったクラスオブジェクトに定数と同じHogeという名前が付けられます(厳密にはこの代入ではまだ名前付けはされませんが)。 class Hoge;(3) def hello(); print "やあ"; end end これは、クラスオブジェクトを作り(ただし、Hoge定数が既に他のクラスオブジェクトを参照していればそれを使います)、そのクラスオブジェクトの名前をHogeにし、Hogeという定数にそのクラスオブジェクトを参照するようにしています。そして、そのクラスオブジェクトにhelloというインスタンスメソッドを登録します。 この(3)でできたクラスオブジェクトは、これ以降、定数Hogeを通じてアクセスすることになります。 Class.newを使って(3)と同じようなことを実現するとすれば、 Hoge = Class.new do def hello() print "やあ" end end とします。ただし、この後に Foo = Hoge と他の定数に代入すると、このクラスオブジェクトの名前は、Fooになる可能性もあります。 >レシーバのHogeというクラスオブジェクトと同名のHogeクラス >の定義を見つけてきてそのインスタンスを作ると クラスオブジェクト自体にそのクラスに関する情報(質問者さんが言うHogeクラスの定義)が全て入ってますので、その情報を元にインスタンスが作られます。
- notnot
- ベストアンサー率47% (4900/10358)
>ただ、 hoge = Class.new()とした場合のhogeインスタンスはこれただのClassクラスのインスタンスですかね?それとも特異クラスになるんでしょうか? ただの「特異クラス」というのは無いと思います。かならず、「オブジェクト これこれの 特異クラス」と、対象となるオブジェクトが存在します。 >hoge = Class.new()とした場合のhogeインスタンスはこれただのClassクラスのインスタンスですかね? 「ただの」という意味が「特異クラスでない」という意味なら、「ただの」インスタンスです。名前がないだけ。 class Fuga < hoge; end p Fuga.ancestores で、hogeの内容が表示されますよね。 >これは Class.new()で作られたインスタンスを代入する先が定数であればその定数名と同じクラスを定義しつつそのClassクラスのクラスオブジェクトを生成するという意味合いでまちがいないでしょうか? あってるような、微妙に違うような。書いてある文字通りに理解した方がいいでしょう。 superclassが指定されてないので、 「新しく名前の付いていないObject のサブクラスを生成します。」 ですね。 >hoge =Class.new()の場合は、やはりhogeというクラスを定義することになるのでしょうか? 無名クラスが生成されて、そのリファレンスがhogeに代入されます。定数に代入されたことのないクラスなので無名のまま。 >クラス定義は定数でなければならないはずですよね。 そんなことはどこに書いてありましたか? 定数に代入されていなければ、無名になるだけです。 >名前のないクラスは、最初に名前を求める際に代入されている定数名を検索し、見つかった定数名をクラス名とします。 これは誤訳かも。 「名前のないクラスは、名前を求める際に、最初に代入されている定数名を検索し、見つかった定数名をクラス名とします。」じゃないかなあ。 irb(main):001:0> foo=Class.new => #<Class:0x26cd2a0> ##この段階では無名のクラス irb(main):002:0> Foo=Bar=foo ## まずBarに代入されてから次にFooに代入される => Bar irb(main):003:0> Foo ## 最初に代入されたのはBarになので、このクラスの名前はBarになった => Bar irb(main):004:0> Bar => Bar
- osamuy
- ベストアンサー率42% (1231/2878)
hoge = Class.newとしたものに対するインスタンスメソッド定義例。こんなのとか: hoge.class_eval do def hello; print "hello.\n"; end end > 必ず先に、特異メソッドを実行しているはずだと思うのですが・・・。 hoge.singleton_methodsが[]なので、実行すべき特異メソッドはないかと。 実行されてるのは、Class#new。
- 参考URL:
- http://www.ideone.com/FN0xp
補足
ああ・・・・・・。また勘違いしてました。 メソッド云々は大丈夫ですが・・・、 ただ、 hoge = Class.new()とした場合のhogeインスタンスはこれただのClassクラスのインスタンスですかね?それとも特異クラスになるんでしょうか? Hoge= Class.newとした場合は普通のクラスオブジェクトが作成されますよね?
補足
ありがとうございます。 順を追って行くとよく理解できました。 hoge = Class.new();(1) Hoge = hoge;(2) class Hoge;(3) def hello(); print "やあ"; end end 上記のように、Class.new(1)でつくったhogeを正規?のクラスオブジェクトとするために Hogeっていう定数に参照を代入。(2) ※ここでようやくHogeがクラスオブジェクトになるっていう感じでしょうか。? 実際にHogeっていうクラスオブジェクトがClassクラスのnewというインスタンスメソッド でレシーバのオブジェクトを作るためにレシーバのHogeというクラスオブジェクトと同名のHogeクラスの定義を見つけてきてそのインスタンスを作ると・・・・。 こんな理解でいいのでしょうか。 少なくとも class Hoge;(3) def hello(); print "やあ"; end end は、純粋にクラスを定義しているだけであり、クラスオブジェクトではないってこと、・・・ですよね? クラスオブジェクトであるHogeは自分と同じ名前を持つクラス定義をコード内から探してきているみたいな。 もしHogeっていう定数に無名クラスを代入して、HogeというクラスをつくっていなかったとしてもObjectクラスのインスタンスメソッドのみを継承してくるようですね。 Hogeっていうクラスオブジェクトが作られた時点で定数と同名のクラスHogeは自動的に 定義されちゃうかんじか・・ふむふむ とにもかくにもこれで先へ進めそうです。 Rubyのシルバー認定試験にはなんとしても受かりたいのでしっかり見に付けておきます。