是否有可能在 Ruby 中获得所有的特征类?
Posted
技术标签:
【中文标题】是否有可能在 Ruby 中获得所有的特征类?【英文标题】:Is it possible to get all the eigenclasses in Ruby? 【发布时间】:2011-12-10 14:36:23 【问题描述】:在 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
我正在尝试获取特征类,因为我想列出脚本中定义的所有方法。我可以查找由模块和类定义的所有实例方法,然后查找模块和类(或所有对象,如果我想占用 CPU)的单例方法,但这似乎有点 hackish。
【问题讨论】:
您最终找到了答案吗?好问题;) 如果不对每个类调用 each_object,我就找不到方法。我确实注意到的一件事是 ObjectSpace.count_objects() :T_CLASS 计数随着每个特征类的创建而增加。那么在 C 领域有可能做到这一点吗? @DanHealy:每个班级的each_object
是什么意思?如classes = ObjectSpace.each_object(Class).to_a; objects = classes.map|klass| ObjectSpace.each_object(klass).to_a.flatten
?
我基本上指的是您在问题中建议的方法:遍历所有对象。
哇哦!我喜欢这个问题。
【参考方案1】:
如果您指的是具有单例方法的对象,这应该可以工作。
eigens = []
ObjectSpace.each_object do |object|
eigens << object unless object.singleton_methods.empty?
end
如果不是,你能澄清一下吗?我将此讨论用作参考:
http://www.ruby-forum.com/topic/77046
【讨论】:
这种方法的主要缺点是遍历每个对象似乎效率低下。 是的。 :-) 这是你需要在你的程序中经常做的事情吗?我很想看看你在做什么,如果你能分享的话。【参考方案2】:我怀疑这是你想要的,但它应该返回所有特征类:
eigens = ObjectSpace.each_object.collect |obj| class << obj; self; end
这确实会将所有特征类的数组分配给变量特征。问题是,除非需要,否则 Ruby 实现可能不会真正创建特征类,而且(我相信)这段代码实际上会为不需要的对象创建特征类。
如果找到更好的方法很重要,我会把这个问题发给任何 Ruby 实现的实现者之一(@yukihiro_matz、@evanphx、@headius 等等)。如果有人知道,他们会的。
【讨论】:
【参考方案3】:从 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)
但是,此代码不会枚举
第一个特征类拥有的私有方法, 2nd, 3rd, ... eigenclasses 拥有的方法。【讨论】:
以上是关于是否有可能在 Ruby 中获得所有的特征类?的主要内容,如果未能解决你的问题,请参考以下文章