27 August 2013
Rubyのメソッドを数えましょう♫
メグ「ねえ、[1,2,3]
みたいな配列オブジェクトに対して呼び出せるメソッドの数って、いくつくらいあるの?」
るびお「えっ?そんなのirb
叩いてRubyに聞けば直ぐわかるじゃん。こうだよ。」
irb> [1,2,3].methods.size
=> 167
るびお「配列オブジェクトはArrayクラスのインスタンスだから、こうしてもいいんだよ。」
irb> [1,2,3].class
=> Array
irb> Array.instance_methods.size
=> 167
メグ「167個もあるの。じゃあ、それが全部Arrayに定義されてるのね?」
るびお「あーそれはね、そうじゃないんだよ。Arrayに定義されてる分を知りたいときは、引数にfalseを渡すんだ。」
irb> Array.instance_methods(false).size
=> 89
メグ「そうなの。じゃあ、残りはどこから来てるの?」
るびお「うん。いい質問だね。それはね、Arrayの祖先から来てるんだよ。祖先が誰かって?それもRubyが教えてくれるよ。ほら。」
irb> Array.ancestors
=> [Array, Enumerable, Object, Kernel, BasicObject]
メグ「るびお君素敵!じゃあ、これらの祖先に定義されたインスタンスメソッドとArrayに定義されたインスタンスメソッドを合わせれば、167個になるのね!」
るびお「そうさ。メグは飲み込みが早いなあ。じゃあ、早速数えてみよう。ほら。」
irb> e = Enumerable.instance_methods(false).size
=> 48
irb> o = Object.instance_methods(false).size
=> 0
irb> k = Kernel.instance_methods(false).size
=> 46
irb> bo = BasicObject.instance_methods(false).size
=> 8
irb> a = Array.instance_methods(false).size
=> 89
irb> e + o + k + bo + a
=> 191
るびお「げっ!」
メグ「るびお君の嘘つき!191個もあるじゃない。24個はどこに消えたのよ!」
るびお「…」
メグ「るびお君、あなたまだまだね。オーバーライド分があるじゃないのよ。Arrayで継承元のメソッドが再定義されてたら、その分は差し引かなきゃ。なんで気が付かないかなあ。じゃあ、論理和してみるわよ。」
irb> Array.ancestors.map{|klass| klass.instance_methods(false)}.inject{|mem,klass| mem | klass }.size
=> 167
るびお「…」
(追記:2013-08-28) 続きを書きました。
blog comments powered by Disqus