Ruby 特異メソッドのnewが先に実行?

このQ&Aのポイント
  • Rubyのインスタンス生成について質問があります。
  • Hoge = Class.new() の場合、Hogeクラスには特異メソッドのみを定義でき、通常のインスタンスメソッドは定義できません。
  • hoge = Class.new() の場合は、クラスオブジェクトではなくただのインスタンスとなります。
回答を見る
  • ベストアンサー

Ruby 特異メソッドのnewが先に実行?

Rubyのインスタンス生成について質問があります。 通常クラスを定義する場合は class Hoge ; def hello(); pirnt "hello"; end であると思います。 ただ Hoge = Class.new(); でもクラスは定義できるとききました。 ただこの場合Hogeクラスに定義できるのは HogeというClassクラスから作られた特異クラスとしてのHogeに 特異メソッドのみを定義できるということですよね? 通常のインスタンスメソッドは定義できませんよね? ではでは、 hoge = Class.new(); とした場合はどうなるのでしょうか? この場合は Classクラスの純粋なインスタンスとなるのでしょうか? 前者の定義とおなじ仕方ですが代入先が、通常の変数です。 この場合は、クラスオブジェクトとして生成されるのですか? オンラインマニュアルをみたところ 「新しく名前の付いていない superclass のサブクラスを生成します。 superclass が省略された時にはObject のサブクラスを生成します。 名前のないクラスは、最初に名前を求める際に代入されている定数名を検索し、見つかった定数名をクラス名とします。」 とあります。 上記内容は Classクラスの特異クラスとして定義されている特異メソッド(new)です。 これは Class.new()で作られたインスタンスを代入する先が定数であればその定数名と同じクラスを定義しつつそのClassクラスのクラスオブジェクトを生成するという意味合いでまちがいないでしょうか? 上記のとおりであれば hoge =Class.new()の場合は、やはりhogeというクラスを定義することになるのでしょうか? クラス定義は定数でなければならないはずですよね。 ただ実際、 p hoge;として出力すると#とひょうじされています。これはhogeがクラスオブジェクトではなく ただのインスタンスであるということでしょうか? であるならばこの hoge = Class.new()の式のnewはClassクラスオブジェクトに定義された特異メソッドではなく Classクラスに定義されたnewメソッド・・・・・つまりClassクラスに定義されたインスタンスメソッドの方のnewメソッドだとおもうのですが・・・・・・。 つまりこちらのメソッドですね。 「new( ... ) クラスのインスタンスを生成して返します。このメソッドの引数はブロック引数も含め initialize に渡されます。」 ※オンラインリファレンスから参照しました。 しかし 通常メソッドの検索は特異メソッドからはじまりその後クラスのインスタンスメソッド->親クラスのメソッドと 検索して行くとあります。 必ず先に、特異メソッドを実行しているはずだと思うのですが・・・。 やはり特異メソッドnewを実行しているのでしょうか? 長々すみませんが、ご教授ください。

  • Ruby
  • 回答数4
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
  • ryu_chan
  • ベストアンサー率37% (69/186)
回答No.3

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の場合はハッシュに順番を付けたので、最初に代入した定数が先に見つかりそういう結果になったのだと思います。

1000vicki
質問者

補足

ありがとうございます。 順を追って行くとよく理解できました。 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のシルバー認定試験にはなんとしても受かりたいのでしっかり見に付けておきます。

その他の回答 (3)

  • ryu_chan
  • ベストアンサー率37% (69/186)
回答No.4

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% (4846/10257)
回答No.2

>ただ、 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)
回答No.1

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
1000vicki
質問者

補足

ああ・・・・・・。また勘違いしてました。 メソッド云々は大丈夫ですが・・・、 ただ、 hoge = Class.new()とした場合のhogeインスタンスはこれただのClassクラスのインスタンスですかね?それとも特異クラスになるんでしょうか? Hoge= Class.newとした場合は普通のクラスオブジェクトが作成されますよね?

関連するQ&A

  • javaで、オブジェクトを生成しないとメソッドは使えないんですか?

    javaで、オブジェクトを生成しないとメソッドは使えないんですか? そのように習ったのですが、サブクラスのメソッド定義の中で、オブジェクトを生成せずにスーパークラスのメソッドを使える例(下に簡単に書きました)をみて、分からなくなってしまいました。 おしえてください、よろしくおねがいします。 ------------------------------- class superclass { method_a(){ ~~~~ } } --------------------------- class subclass { method_b(){ super.method_a(); }

    • ベストアンサー
    • Java
  • Ruby言語に関して質問です。

    Rubyで、クラス定義の際の質問です。 通常 cattle= Class.new(); で引数がデフォルトの場合は、Objectクラスのサブクラス生成すると 公式のリファレンスに記述があります。 調べてみると上記コードの場合は,cattleという無名クラスと呼ばれるものになるそうです。 この無名クラスとはYUGUIさんのサイトにある http://yugui.jp/images/uploaded/20084013-metaclass.png 右端の列にあるメタクラスと呼ばれるものになるのでしょうか? (無名クラス と メタクラスは同義??) また上記URLの画像からメタクラスはClassクラスのインスタンスであるようです。 ただClass.newで実行される newというクラスメソッドってサブクラスを生成すると いうふうにリファレンスにありますがレシーバであるClassクラスのインスタンスを 返すという記述はありません。 ただ、おそらくメタクラスというのはClassクラスのインスタンスなのだとは思いますが、 この理由はなぜなのでしょうか? もう一点、p Cattle.class();と記述すると Classクラスが返ると思います。これはCattleクラスのClassクラスのインスタンスである ということになるのでしょうか? しかしながらYUGUIさんの画像ではCattleはメタクラスのインスタンスとなっています。 であれば、メタクラスを意味するのでしょうか? 公式リファレンスには、上記に書いたような関係はRubyを扱う際には特に問題ではないとありますが、気になっています。

    • ベストアンサー
    • Ruby
  • Ruby インスタンスの初期化について

    newメソッドを使わずにinitializeメソッドを定義しただけで インスタンスが作成されて初期化までされる理屈について 教えていただけないでしょうか? またクラスを作るときに基となっているObjectクラスとは一体 何物なのか、教えて頂きたい。 例 01:#Sampleクラスを作る 02:class Sample 03: #Samlpeクラスのインスタンスを初期化 04: def imitialize( lv, hp ) 05: end 06:end ↑の場合インスタンスlvとhpは、「lv = sample.new( 0 )」などと言う ように定義されてない。 それにnewメソッドでインスタンスを作りそこに数値の0を代入できるなら そもそもinitializeで初期化する必要は無いのではないでしょうか? 有識者の方いらっしゃいましたら、ご説明をよろしくお願いします。

    • ベストアンサー
    • Ruby
  • 書籍 メタプログラミングRubyの中の一文

    上記書籍のP143の カレントクラスについて質問です。 上記書籍に、 【クラス定義のなかでは、カレントオブジェクトselfは定義されたクラスである】 という記述がありますが 例えば、以下のようなクラス定義あがあるとします。 class Test print self.class def self.method_01() print "メソッド01" end def method_02() return self end end クラス定義内に3箇所selfが存在しますが、 インスタンスメソッド の method_02()内のselfはnewメソッドによって 作成されたTestクラスのインスタンスの意味だと思います。 それより上の二つのselfは確かに定義中のカレントオブジェクト・・つまりTestクラス ですけれど、なぜ書籍では、クラス定義内でのselfという表現なのでしょうか? 個人的には、【クラス定義内で定義されるインスタンスメソッド内にあるselfを除くselfはカレントオブジェクトである】という風に、説明すべきだと思うのですが 何か私の解釈に誤りがあるのでしょうか?それとも、文面を気にしすぎなだけでしょうか? くだらない質問ですがご意見をおきかせください。

    • ベストアンサー
    • Ruby
  • super( )メソッドについて質問です

    サブクラスのコンストラクタの定義をするときにsuper()メソッドを使うときはどういうときですか?また、どうしてsuper()メソッドを使って、スーパークラスのインスタンスを作成しないといけないのですか?教えてください。

    • ベストアンサー
    • Java
  • 自クラスをnewしたインスタンスの参照

    また、よろしくおねがいします。 あるインスンタンス(A)から別のクラスをnewしてインスタンス(B)を作成し class A{ public A(){} B b = new B(); public hoge(){ System.out.plintln("hoge"); } } class B{ public B(){} A.hoge(); <<= ここから自クラスをnewしたAのhoge()を起動させたい } こんな風にnewされたB側からAのメソッドを動かしたいなんて場合は、どのようにするんでしょうか?

    • ベストアンサー
    • Java
  • 【Ruby】Protectedの確認プログラム

    こんにちは、Ruby初学者です。 以下の問題が解けずに困っています。「protectedが、メソッドをクラス内部から使えるようにする。また、同一クラス内ではインスタンスメソッドとしても使えるようにする。」という教科書的な内容は理解しているつもりでプログラムを書くのですが、どうも上手くいきません。 ヒントだけでも構いませんので、諸兄姉の知識をお貸しいただければ幸いです。 「protectedと宣言されたメソッドは、そのメソッドが定義されているクラスのサブクラスで定義されているメソッドから、メッセージの送信元とは異なるオブジェクトに対しても呼び出せることを確認するプログラムを作成し、結果を説明せよ。」 よろしくおねがいいたします。

    • ベストアンサー
    • Ruby
  • クラスメソッドのインスタンスメソッドからの呼び出し

    クラスメソッド“say”を定義しました。 クラス外からこれを呼び出すときは Hoge.say 'hello' で、同じクラス内の、インスタンスメソッド“hello”からクラスメソッド“say”を呼び出したいとき、クラス外から呼び出すのと同じように呼び出すことはできました。 class Hoge  def self.say(word)   puts word  end  def hello   Hoge.say('hello')  end end しかし、メソッド“hello”内にHogeというクラス名を直書きしたくないのですが、どんな文法を使用すればよろしいでしょうか? # Hoge#hello内での試行錯誤 self.say 'hello' => エラー say 'hello' => エラー ひょっとして、クラス名を直書きする以外手段はないのでしょうか・・?

    • ベストアンサー
    • Ruby
  • メソッドにより複数の情報を得たい場合

    例えば、他のクラスのメソッドに何らかのインスタンス配列を渡してやって、その中から何らかの基準で選択して要素を返すようなメソッドを考えます。 さらに、同時に配列のどの位置が選ばれたのかを知りたい場合は、みなさんならばどう対処しますか? class Hoge{} class A {  public Hoge select(Hoge h[]){   return h[(int)(Math.rand()*h.length)];  } } class Test{  public static void main(String argv[]){   A a = new A();   Hoge hoge[] = new Hoge[100];   Hoge h = a.select(hoge);//同時にどの位置が選択されたかも知りたい  } } 上の例だと、「最初から選択された位置を返して、それからHogeインスタンスを得ればいいじゃないか」という話もごもっともなのですが、もし仮にJavaがポインタを許すと仮定した場合の Hoge select(Hoge h[], int *n){   return h[*n = (int)(Math.rand()*h.length)]; } Hoge h = select(hoge, &idx); に代わるような方法はないものかなぁ。。 という素朴な疑問から質問をしてみました。 考え付いた方法は、サイズ1のint配列を引数に渡して値をセットするか, 欲しい値などをメンバにもつクラスを定義してやって、それを select から返す方法か・・くらいです。 みなさんならこういった場合(メソッドにより取得したい値がいっぱいある場合) 、どうしますか?

    • ベストアンサー
    • Java
  • 【ruby】【文法】スパークラスのスーパークラスのメソッドを呼び出したい

    スパークラスのスーパークラスのメソッドを呼び出したいです。 たとえば、Hoge3のスーパークラスがHoge2で、さらにそのスーパークラス がHogeの時、Hoge3からHogeのメソッドを呼び出したいのです。 もう少し具体的に説明させてもらいます。 class Hoge  def initialize()   @name='hoge'  end end class Hoge2 < Hoge  def initialize()   super   @name='hogehoge'  end end class Hoge3 < Hoge2  def initialize()   super #これではスーパークラスHoge2のメソッドが呼ばれてしまう。   puts @name  end Hoge3.new() 上記実行結果は、hogehogeが出力ですが、 スーパークラスのスーパークラスが設定した@name値、 'hoge'が出力されるようにしたいです。 『Hoge3クラスはHoge2クラスを継承すればよいではないか?』 とも思うでしょうが、Hoge2クラスには、Hogeには無い機能が多く拡張されてると考えてください。 ご指導のほど、宜しくお願いいたします。

専門家に質問してみよう