当发送消息时,Ruby对象会搜索它是否有一个按该名称响应的方法。它的方法查找按以下顺序搜索,并使用它找到的第一种方法。
Module.prepend
存在之前编写的) 或者,更简单地说,它会按照列出的顺序查看self.class.ancestors
中的所有内容。
在调用方法时遵循此查找路径;如果您创建一个类的实例,然后重新打开该类并添加一个方法或通过模块混合一个方法,现有实例将获得对该方法的访问权。
如果所有这些都失败了,它会查看它是否有method_missing
方法,或者它的类是否有,它的父类等等。
我的问题是:除了手动检查代码或使用puts "I'm on module A!"
之类的示例方法外,您能告诉给定方法的来源吗?例如,您可以吗?列出一个对象的方法,看看“这个是在父类上,这个是在模块A上,这个是在类上并覆盖父类,”等等?
答案 0 :(得分:25)
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}"}
答案 1 :(得分:9)
获取相应的Method(或UnboundMethod)对象并询问其owner
。因此,您可以执行method(:puts).owner
并获取Kernel
。
答案 2 :(得分:6)
要查找在A
上定义的实例方法(但不在超类上定义):
A.methods(false)
要查找在A
及其超类上定义的实例方法:
A.methods
要查找定义给定方法的类(或模块):
method(:my_method).owner
要查找哪个对象是给定方法的接收者:
method(:my_method).receiver
答案 3 :(得分:1)
您可以使用Object#method
。例如,
[1, 2, 3].method(:each_cons) # => #<Method: Array(Enumerable)#each_cons>
告诉Array的each_cons方法来自Enumerable模块。