Hatena::ブログ(Diary)

[サ]ロンパスの日記 このページをアンテナに追加 RSSフィード

08-02-27

[]トップオブジェクトが持つClassを全部表示する方法 22:53 トップオブジェクトが持つClassを全部表示する方法を含むブックマーク トップオブジェクトが持つClassを全部表示する方法のブックマークコメント

よくrequire()してコードを書いていると、今いる階層にはどんなクラスが存在するのか

一覧を見てみたくなりませんか?

実は、id:akio0911に「Rubyでクラス一覧を表示する方法知らない?」と聞かれたので

調べてみました。

答え

self.class.constants.reject{|constant| eval("!#{constant}.kind_of?(Class)")}

・・・えーと。はい。よくわからないと思うのでもう少しわかりやすく書きます。

self.class #=> Object

トップオブジェクトのクラスを返してもらいます。

self.class.constants #=> ["TrueClass", "CROSS_COMPILING", ... ]

トップオブジェクトが持つコンスタンスを配列として返してもらいます。

この配列の中には、トップオブジェクトが所持する定数、クラス、モジュールのすべてが

格納されています。

self.class.constants.reject{|constants| <条件式> }

<条件式> を満たすものを配列から除外します。

今回の場合は、「クラス一覧を表示」したいので、クラス以外を除外します。

なので、条件式は

eval("!#{constant}.kind_of?(Class)")

と、なります。

詳しく解説すると、eval(String)というのは

与えられた文字列をRubyの実行文として実行するという一風変わったメソッドです。

ここで与えられた内容は、

"!#{constant}.kind_of?(Class)"

ですね。

これをさらに詳しく解説すると、Object.kind_of?(Class)というのは

Objectが与えられたClassと等しいか?をtrueかfalseで返します。

ここでは#{constant}というなぞのオブジェクトを示していますが

これはブロックに与えられたconstant変数を示しますね。

気をつけてほしいのは、先頭についてる「!」です。

これは、ビット反転といって、trueならfalseに、falseならtrueとして解釈するという

天邪鬼な代物です。

つまり、!Object.kind_of?(Class)という場合は

ObjectがClassと等しい場合はtrue・・・の反対「false」となります。

結果としては、トップオブジェクトが持つクラスを全部表示してくれるわけですね。

ちなみに

self.class.constants.reject{|constant| eval("!#{constant}.kind_of?(Module)")}

このようにすると、トップオブジェクトが持つモジュールを全部表示してくれます。

いろんなコードやライブラリrequireしすぎて、今どのクラスがあるのかわからなくなった

ときには便利かもしれませんね。

shingotadashingotada 2008/02/27 18:24 メモリの消費を抑えられるとか効果あるんでしょうか?

saronpasusaronpasu 2008/02/27 18:32 ruby -rprofile hoge.rb と実行してみると、実行時間計測できます。
上記のコードの場合はあまり差がないけど、require()やautoload()で読み込む対象のファイルに書かれているオブジェクトが多くなるほど、それに比例してrequire()で全部読んだ場合のコードが遅くなるんじゃないかと思っています。

yowayowa 2008/02/28 02:29 rejectの否定より、select(か別名のfind_all)の方が素直かも。

リンク元