メソッドがどのクラスで定義されているかを調べる直接的な方法


再開(?)後、みょーにリフレクションづいている rubyco さんに影響されて SqueakSmalltalk でどうなっているのか調べてみました。


追記
コメント欄にて nurse さんが暗にご指摘のとおり、おそらく、rubyco さんのおっしゃっておられる意味あいのものは、すでに id:sumim:20060514:p1 にて言及済みの #whichClassIncludesSelector: や 小飼 さんの Perl における UNIVERSAL::which に類似の機能だと思います(残念ながら Ruby にはこうした機能はありませんが、実現は容易なはずです)。しかしここでは、メソッド名でだぐるのではなく、当初の私の勘違いを貫いてw、あえてメソッドオブジェクト自身に聞いて調べる方法を紹介しています。あしからず。


最初、なーんだ、Ruby にはそんなものもないのか…とかバカにしていたら Smalltalk でも一発ではできなかった。orz (補足: これは Squeak3.8 のはなしで、Squeak3.9 からは #methodClass が使えるようになりました。)

| method |
method := Object >> #inspect.

^ method who first
=> Object

#who を介する必要があります。いやーな予感がして調べてみると、この #who 自体もじつに泥臭い。クラスのメソッド辞書を虱潰し…。orz

CompiledMethod >> who
   "Answer an Array of the class in which the receiver is defined and the 
   selector to which it corresponds."

   | sel |
   self systemNavigation allBehaviorsDo: [:class | 
      (sel := class methodDict keyAtIdentityValue: self ifAbsent: [nil]) 
         ifNotNil: [^Array with: class with: sel]].
   ^ Array with: #unknown with: #unknown