🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

2回答

1750閲覧

Rubyの特異クラスを見分けるには?

Pyons04

総合スコア19

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

1クリップ

投稿2019/09/12 14:36

編集2019/09/12 14:39

Rubyの特異クラスについて勉強中です。

Rubyの特異クラスは、特異クラスを定義したインスタンスを生成したクラスの下に、さらにもう一つ無名クラスを継承されてインスタンス化しているのだと理解しています。

もちろん、特異クラスから生成されたインスタンスに対して、instance.classやinstance.ancestorsによって、無名クラスの存在を知ることはできず、それはユーザーが無名クラスの存在を感じなくて済むようなRubyの仕様の工夫である、と理解しています。

では、実際にそのインスタンスが特異クラスから生成されたものであるかを知るにはどのような方法があるのでしょうか?以下2通りの方法を試してみたのですが、うまくいきませんでした。

  • 特異クラスを定義していない2つのインスタンスのクラスと定義したインスタンスのクラスのobject_idを比較を比較し、特異クラスを定義したインスタンスだけが違うobject_idを持っているから、特異クラスであることがわかる。

  • 特異クラスを定義したインスタンスに対してinstance.class.singleton_class?でtrueを返す。

ruby

1class Icecream 2 def flavor 3 p "chocolate" 4 end 5end 6 7ic = Icecream.new 8ic2 = Icecream.new 9ic3 = Icecream.new 10def ic.melt 11 return false 12end 13 14p ic.class.object_id 15p ic2.class.object_id 16p ic3.class.object_id 17 18p ic.class.singleton_class?

しかし、実際に得られたのはのような結果でした。
object_idはすべて同じで、 singleton_class? はfalseを返してしまします。

70368599643720 70368599643720 70368599643720 false

自分はRubyのオブジェクト指向を全く勘違いしているのでしょうか?それとも特異クラスであると見分ける方法が他にあるのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

実際にそのインスタンスが特異クラスから生成されたものであるかを知るにはどのような方法があるのでしょうか?

整数やtruefalsenilのような特殊な事例を除いて、すべてのインスタンスは特異クラスを持ち「え」ます。そして、特異クラスはObject#singleton_classなど、特異クラスにアクセスしようとした瞬間に生成されます(るりま)ので、区別はできません

そして、Object#classで取れるのは特異クラスではありません。

投稿2019/09/12 23:24

編集2019/09/13 14:15
maisumakun

総合スコア145971

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Pyons04

2019/09/13 13:40

maisumakun様 ご回答ありがとうございます。 返信おくれまして、申し訳ありません。 「全てのインスタンスが特異クラスを持っている」とはどういうことでしょうか? 全てのインスタンスは設計図であるクラスから生成されますから、インスタンスが必ず生成元のクラスを持っているのはわかります。 しかし、特異クラスが「一つのインスタンスに対して同じクラスから生成された他のオブジェクトとは異なる特徴を与えるための特殊なクラス」なのだから、ユーザーが定義したインスタンスにだけ存在すると、自分は認識してしまっています。 全てのインスタンスは初期化の際(.newされたときに既に)に生成元のクラスとは他に、特異クラスももっているものなのでしょうか?もしそうなのであれば、(ユーザーが特異クラスを定義しなければ)どんな役割を普段は持っているのでしょうか? お時間あるときに回答いただけると幸いです。
maisumakun

2019/09/13 14:14

すみません、誤りがありましたので回答を修正しました。 とはいえ、Ruby上で「空の特異クラスがあるオブジェクト」と「特異クラスのないオブジェクト」を区別するすべがありません(後者のオブジェクトについても、特異クラスへアクセスした瞬間に前者のオブジェクトに変化する)ので、Rubyでプログラミングする上ではこの2つの差異は無視できます。
Pyons04

2019/09/14 02:02 編集

maisumakun 様 丁寧にご回答くださりありがとうございます。 singleton_class?というメソッドをインスタンスに使うことで、特異クラスから生成されたのか、知ることが出来るのではないかと思っていたのですが、やはり無理なのですね。 ic.singleton_class.instance_methods(false)のように、他のインスタンスと比較して新しいメソッドが追加されているかどうかチェックするより方法はないのですね。 ありがとうございました。
guest

0

ベストアンサー

特異クラスから生成されたインスタンス

特異クラスからインスタンスを生成することはできません。
コードを見ると「得意メソッドを持つインスタンス」という意図ですかね?

「このオブジェクトは得意メソッドを持つか?」の判断なら、ic.singleton_methods==[]でしょうか。

投稿2019/09/12 14:54

otn

総合スコア85888

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Pyons04

2019/09/12 23:13 編集

otn様 迅速な回答誠にありがとうございます。 そして返信が遅くなったことお詫びします。 自分の認識ではクラスとは「インスタンスを生成するための設計図」だと認識しています。 (Rubyではclassすらclassクラスのインスタンスなのでややこしいですが) ですから、「特異クラス」もあくまで「クラス」であるのだからインスタンスを生成することが可能であると考えていました。 ですがotn様の仰る通り「特異クラスからインスタンスを生成することはでき」ないのであれば、「特異クラス」とはあくまで、(インスタンスに新しいメソッドを追加するという)インスタンスに対する操作であり、インスタンスの設計図である「クラス」に対して何らかの操作が行われている訳ではない、ということなのでしょうか? お手隙の際回答いただけると幸いです。よろしくお願いいたします。
otn

2019/09/13 01:42

特異クラスは、特異メソッドを定義するためのものです。 言語の構造として、通常のメソッドはクラスに属すので、統一化のために、特異メソッドもクラスに属することになっているんだと思います。 オブジェクトの特異メソッドは、 ic.singleton_methods でわかりますが、他のクラスと同じように、クラスのインスタンスメソッド一覧を取得しても同じです。 ic.singleton_class.instance_methods(false) 「クラスに対して何らかの操作が行われている訳ではない」ということは無いです。
Pyons04

2019/09/13 04:45

otn 様 特異クラス「クラスに対して何らかの操作が行われている」のであれば、それがクラスインスタンスのobject_idの変化のような形で可視化できるのではないかと思ったのですが、そのような方法はないという事なのですね。 もちろんotn様の仰る通り、ic.singleton_class.instance_methods(false)で、特異メソッドが追加された事がわかれば、特異クラスから生成されたインスタンスであると知る事ができるので、実用上の問題はありません。 丁寧に回答してくださり、ありがとうございます。
otn

2019/09/13 04:48

オブジェクトを操作しても、object_idは変化しませんが、そういうことではない??
Pyons04

2019/09/13 04:58

特異クラスが定義された時点で、新しい別のIcecreamクラスが生成されるのでは?と思ったのです。そのクラス(特異クラス.object_id)は別のobject_idを持っているはずで、それで変化がわかるのではないかと思いました。
otn

2019/09/13 05:37

ice.classとic.singleton_classは別のものですよ。 特異クラスは、特異メソッドを定義したときに自動生成されますが、singleton_classメソッドを実行したときにも自動生成されるとかだったと思います。
Pyons04

2019/09/14 02:18 編集

otn 様 otn様の仰る通り、メソッドに.singleton_classを実行した時点で特異クラスが生成されてしまうようです。直接的に、特異クラスの存在の有無をチェックする手立てがないということがわかってきました。ある意味(特異クラスの存在を隠せるような)よくできた言語仕様ということなのかもしれません。 余談ですが特異クラスから生成されたインスタンスに「p ic.methods(false)」を使うことで、特異クラスで定義されたメソッドだけを表示することが出来るようなので、それが最も簡単な方法に思えます。通常のインスタンスでは空の配列が返ってきました。(https://docs.ruby-lang.org/ja/latest/method/Object/i/methods.html) ご丁寧に解説してくださり、ありがとうございます。大変勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問