こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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を実行しているのでしょうか?
長々すみませんが、ご教授ください。

投稿日時 - 2011-08-20 10:58:47

QNo.6954982

すぐに回答ほしいです

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

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

投稿日時 - 2011-08-24 12:35:21

補足

ありがとうございます。
順を追って行くとよく理解できました。

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のシルバー認定試験にはなんとしても受かりたいのでしっかり見に付けておきます。

投稿日時 - 2011-08-24 23:55:08

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.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クラスの定義)が全て入ってますので、その情報を元にインスタンスが作られます。

投稿日時 - 2011-08-25 10:05:40

ANo.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

投稿日時 - 2011-08-20 23:24:34

ANo.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

投稿日時 - 2011-08-20 22:20:28

補足

ああ・・・・・・。また勘違いしてました。

メソッド云々は大丈夫ですが・・・、
ただ、 hoge = Class.new()とした場合のhogeインスタンスはこれただのClassクラスのインスタンスですかね?それとも特異クラスになるんでしょうか?

Hoge= Class.newとした場合は普通のクラスオブジェクトが作成されますよね?

投稿日時 - 2011-08-20 22:37:04

あなたにオススメの質問