2010-08-16 49 views
24

發送消息時,Ruby對象將搜索以查看它是否具有該名稱的方法來響應。其方法查找按以下順序搜索,並使用它找到的第一個方法。紅寶石 - 確定方法的起源?

  1. 上本身定義singleton方法在其類中定義
  2. 方法(在其「eigenclass」又名方法)
  3. 任何模塊混入它的類,在夾雜物的相反的順序(僅是最早的夾雜物給定的模塊有任何影響 - 如果超類包含模塊A,並且子類再次包含它,則在子類中將被忽略;如果子類包括A,則B和A,第二個A將被忽略)(更新:請注意,此之前寫有Module.prepend
  4. 其父類
  5. 混入父類,父父,等

或者,說得簡單些,它看起來對自己的任何方法,那麼一切都在self.class.ancestors在爲了他們上市。

這個查找路徑是在調用該方法的時刻;如果您創建了一個類的實例,然後重新打開該類並添加一個方法或通過一個模塊混合一個方法,那麼現有實例將獲得對該方法的訪問權限。

如果所有的失敗,它看起來,看它是否有一個method_missing方法,或者如果它的類呢,它的父類等

我的問題是這樣的:除了檢查用手工代碼或者使用例如puts "I'm on module A!"這樣的示例方法,你能說出給定的方法來自何處嗎?例如,你可以列出一個對象的方法,並且看到「這個是在父類上,這個在模塊A上,這個在類上,並且覆蓋了父類,」etc?

回答

22

Object#method返回Method對象,提供有關給定方法的元數據。例如:

> [].method(:length).inspect 
=> "#<Method: Array#length>" 
> [].method(:max).inspect 
=> "#<Method: Array(Enumerable)#max>" 

在Ruby 1.8.7和以後,就可以使用Method#owner來確定所限定的方法的類或模塊。

要獲得所有與他們的定義,你可以做類似下面的類或模塊的名稱的方法列表:

obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"} 
+0

您可以通過使用backports gem來獲取1.8.6中的#owner方法。 – rogerdpack 2010-08-17 15:48:25

+5

另一個精彩的地方:'Method'對象也有'source_location'方法。 「現在那個討厭的猴子補丁在哪裏?」:) :) – 2012-07-04 12:40:58

+0

不能相信我對此沒有想法。非常有用!非常感謝。 – dimitarvp 2015-07-23 11:34:16

9

獲取適當的方法(或UnboundMethod)對象並請求其owner。所以你可以做method(:puts).owner並得到Kernel

+0

您的答案與接受的答案一起是黑暗中的純光人。謝謝! – dimitarvp 2015-07-23 11:35:06

1

您可以使用Object#method。例如,

[1, 2, 3].method(:each_cons) # => #<Method: Array(Enumerable)#each_cons> 

表明Array的each_cons方法來自Enumerable模塊。

4

要找到哪個實例方法上A定義(但不是超):

A.methods(false) 

要找到哪個實例方法上A定義和其超:

A.methods 

找哪家類(或模塊)給定的方法定義如下:

method(:my_method).owner 

要查找給定方法的接收器是哪個對象:

+0

要獲取特定類型的方法:someobject.private_methods,someobject.public_methods,someobject.protected_methods,someobject.singleton_methods,SomeClass.instance_methods,SomeClass.private_instance_methods,SomeClass.protected_instance_methods,SomeClass.public_instance_methods(與.instance_methods相同)。 – 2010-10-23 11:24:49

+0

'A.methods'應爲'A.instance_methods' – Kelvin 2012-02-23 17:06:55