我正在学习一些元编程,我一直试图找到一种方法。假设我有以下课程:
class MyClass
def self.my_method
end
def your_method
end
end
使用以下代码,我可以在对象空间中搜索每个方法:
type = Class
name = /^my_method$/
result = ObjectSpace.each_object(type).select do |o|
o.instance_methods(false).grep(name).size > 0 || o.methods.grep(name).size > 0
end
p result
它发现它显示以下输出:
[MyClass]
由于搜索器代码也会搜索实例方法,因此在查找your_method时会显示相同的输出。
即使我向对象添加单例方法:
mc = MyClass.new
def mc.our_method
end
只需改变搜索者:
type = Object
name = /^our_method$/
result = ObjectSpace.each_object(type).select do |o|
o.methods.grep(name).size > 0
end
p result
它也找到了它:
[#<MyClass:0x8f86760>]
问题是,如何找到顶级对象中定义的方法?这个方法:
def hidden
end
此外,在定义这样的方法时,哪个是当前类?
答案 0 :(得分:5)
定义这样的方法时,哪个是当前的类?
我们可以通过检查此顶级范围中的self
来轻松找出我们所处的对象:
self #=> main
self.class #=> Object
所以我们不是一个Class,而是一个被称为“main”的Object实例。
如何找到顶级对象中定义的方法?
这是有趣的地方。 Ruby中的顶级范围对象具有特殊的行为,但是发现这里定义的方法所处的位置相对容易:
def foo; :bar; end
method(:foo).owner #=> Object
Object.new.foo #=> NoMethodError: private method `foo' called
Object.new.send(:foo) #=> :bar
因此,在顶层定义的方法是Object的(private *)实例方法。您的“搜索者”无法找到它的原因是因为这些方法是私有的,methods
和instance_methods
都不包含私有方法,而是您需要private_methods
和private_instance_methods
:
Object.instance_methods.include?(:foo) #=> false
Object.private_instance_methods.include?(:foo) #=> true
*请注意,Pry(至少v0.10.1)会改变这一点,以便在其REPL公共场所的顶层定义方法。
答案 1 :(得分:0)
如果你有这个:
def my_method() end
class A
def self.my_method() end
end
class B < A
def my_method() end
end
class C
def my_method() end
end
并希望找到您创建的名为'my_method'
的方法,您可以这样做:
ObjectSpace.each_object(Class).select do |o|
o.instance_methods(false).include?(:my_method)
end
#=> [C, B]
ObjectSpace.each_object(Class).select do |o|
o.methods(false).include?(:my_method)
end
#=> [A]
ObjectSpace.each_object(Class).select do |o|
o.private_instance_methods(false).include?(:my_method)
end
#=> [Object]