Как мне получить класс экземпляра BasicObject?

У меня есть сценарий, который выполняет итерацию с использованием ObjectSpace # each_object без аргументов. Затем он печатает, сколько экземпляров существует для каждого класса.

Я понял, что некоторые классы переопределяют метод экземпляра #class , поэтому мне пришлось найти другой способ получить реальный класс; Допустим, он хранится в переменной "класс" , а klass === object истинно.

В Ruby 1.8 я мог это сделать, предполагая, что Object не был исправлен обезьяной:

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 это больше не работает:

# 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 . Последнее сделано для подкласса :: BasicObject в Ruby 1.9, поэтому Object исключен из цепочки наследования. Этого не происходит и не может происходить в Ruby 1.8, поэтому ActiveSupport :: BasicObject является подклассом Object .

Я не нашел способа определить реальный класс объекта Ruby 1.9, который не является экземпляром объекта . BasicObject в 1.9 действительно скудный:

BasicObject.instance_methods
=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]

Идеи?

ОБНОВЛЕНИЕ:

Поскольку срок службы Ruby 1.9 подошел к концу, я меняю свое согласие на ответ @ косвенный. Вышеупомянутые упоминания о рубине 1.9 предназначены только для исторических целей, чтобы показать, что изменение с 1.8 на 1.9 было первоначальной причиной моей проблемы.

21
задан Kelvin 13 November 2017 в 19:44
поделиться