如何获取 BasicObject 实例的类? [英] How do I get the class of a BasicObject instance?

查看:33
本文介绍了如何获取 BasicObject 实例的类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个脚本,它使用 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::DurationActiveSupport::BasicObject 的子类.后者在 Ruby 1.9 中被用于子类 ::BasicObject,因此 Object 被排除在继承链之外.这不会,也不能在 Ruby 1.8 中发生,所以 ActiveSupport::BasicObjectObject 的子类.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆