如何获取 BasicObject 实例的类? [英] How do I get the class of a BasicObject instance?
问题描述
我有一个脚本,它使用 ObjectSpace#each_object
进行迭代,没有参数.然后它打印每个类存在多少个实例.
I have a script that iterates using ObjectSpace#each_object
with no args. Then it prints how many instances exist for each class.
我意识到有些类重新定义了#class
实例方法,所以我不得不寻找另一种方法来获取实际的类;假设它存储在变量 "klass"
中,并且 klass === object
为真.
I realized that some classes redefine the #class
instance method, so I had to find another way to get the actual class; Let's say it's stored in variable "klass"
, and klass === object
is true.
在 Ruby 1.8 中我可以做到这一点,假设 Object
没有被monkeypatched:
In Ruby 1.8 I could do this, assuming Object
wasn't monkeypatched:
Object.instance_method(:class).bind(object).call
这适用于 ActiveSupport::Duration
实例:
# Ruby 1.8
# (tries to trick us)
20.seconds.class
=> Fixnum
# don't try to trick us, we can tell
Object.instance_method(:class).bind(20.seconds).call
=> ActiveSupport::Duration
但是,在 Ruby 1.9 中这不再有效:
But, in Ruby 1.9 this no longer works:
# Ruby 1.9
# we are not smart...
Object.instance_method(:class).bind(20.seconds).call
TypeError: bind argument must be an instance of Object
from (irb):53:in `bind'
from (irb):53
from /Users/user/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `<main>'
事实证明,ActiveSupport::Duration
是 ActiveSupport::BasicObject
的子类.后者在 Ruby 1.9 中被用于子类 ::BasicObject
,因此 Object
被排除在继承链之外.这不会,也不能在 Ruby 1.8 中发生,所以 ActiveSupport::BasicObject
是 Object
的子类.
It turns out that ActiveSupport::Duration
subclasses ActiveSupport::BasicObject
. The latter is made to subclass ::BasicObject
in Ruby 1.9, so Object
is excluded from the inheritance chain. This doesn't, and can't, happen in Ruby 1.8, so ActiveSupport::BasicObject
is a subclass of Object
.
我没有找到任何方法来检测不是 Object
实例的 Ruby 1.9 对象的实际类.1.9 中的 BasicObject
真的很简单:
I haven't found any way to detect the actual class of a Ruby 1.9 object that isn't an instance of Object
. BasicObject
in 1.9 is really bare-bones:
BasicObject.instance_methods
=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
想法?
更新:
自从 ruby 1.9 生命周期结束,我将接受更改为@indirect 的答案.上面提到的 ruby 1.9 只是为了历史目的,表明从 1.8 到 1.9 的变化是我问题的根源.
Since ruby 1.9 reached end-of-life, I'm changing my accept to @indirect's answer. The mentions of ruby 1.9 above are merely for historical purposes, to show that the change from 1.8 to 1.9 was the original cause of my problem.
推荐答案
如果你可以升级到 Ruby 2.0,你根本不需要实现任何东西:
If you can upgrade to Ruby 2.0, you don't need to implement anything at all:
>> Kernel.instance_method(:class).bind(BasicObject.new).call
=> BasicObject
这篇关于如何获取 BasicObject 实例的类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!