能否在Ruby中获取所有的特 eigenclass?

13

在 Ruby 中获取所有模块的列表很容易:

ObjectSpace.each_object(Module).to_a

然而,是否有可能获取所有特异类(也称为单例类或元类)的列表?或者特异类是不可见的?

我尝试过:

str = "foo"
my_metaclass = class << str; self; end
my_metaclass.class == Class # my_metaclass' class is Class
ObjectSpace.each_object(Class).include?(my_metaclass) # false
ObjectSpace.each_object.include?(my_metaclass) # still false
# Just to show each_object works
ObjectSpace.each_object(Class).include?(String) # true
我试图获取特殊类(eigenclasses),因为我想列出在脚本中定义的所有方法。我可以查找模块和类定义的所有实例方法,然后查找模块和类的单例方法(或所有对象的单例方法,如果我想要消耗 CPU),但这似乎有点 hackish。

你最终找到了这个问题的答案吗?好问题 ;) - 2potatocakes
我找不到一种方法来做到这一点,而不是在每个类上调用each_object。但我注意到的一件事是,ObjectSpace.count_objects():T_CLASS计数会随着每个特殊类的创建而增加。因此,在C语言中可能可以实现这一点? - Dan Healy
我基本上是在提及你在问题中建议的方法:遍历所有对象。 - Dan Healy
你一定在做一些非常元的事情。=P - thomasfedb
@thomasfedb:我正在开发一个东西,如果有一个未被处理的method_missing,它会显示类似于“:foo在YourFirstClass中没有被实现,但是在YourOtherClass中已经实现了”。我需要很快把它放到github上。 - Andrew Grimm
显示剩余2条评论
3个回答

2
如果您的意思是指具有单例方法的对象,那么这应该可以工作。
eigens = []
ObjectSpace.each_object do |object|
  eigens << object unless object.singleton_methods.empty?
end

如果不行,你能否澄清一下?我把这个讨论当作参考:http://www.ruby-forum.com/topic/77046

这种方法的主要缺点是迭代每个对象似乎效率低下。 - Andrew Grimm
这很好。 :-) 这是你的程序中需要经常做的事情吗?如果你能分享一下,我很想看看你在做什么。 - sheldonh

1

我怀疑这不是你想要的,但它应该返回所有的特殊类:

eigens = ObjectSpace.each_object.collect { |obj| class << obj; self; end }

这确实会将所有特异类的数组分配给变量eigens。问题是,Ruby实现可能不会创建特异类,除非有需要,而且我相信这段代码实际上会为那些不需要特异类的对象创建特异类。

如果找到更好的方法很重要,我建议在Twitter上向任何一个Ruby实现者(@yukihiro_matz、@evanphx、@headius等)提问。如果有人知道,他们就会知道。


1

截至MRI 1.9版本,似乎不支持特征类枚举。因此,没有一种100%可靠的方法来迭代所有方法。最好的整体方法枚举器的近似方法如下:

methods = []

ObjectSpace.each_object { |x|
  if x.kind_of?(Module)
    methods += x.public_instance_methods(false) +
               x.protected_instance_methods(false) +
               x.private_instance_methods(false)
  end
  methods +=   x.singleton_methods(false)
}

然而,这段代码将不会枚举:

  • 第一类特征类所拥有的私有方法
  • 第二、三、……类特征类所拥有的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接