У меня есть сценарий, который выполняет итерацию с использованием 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 было первоначальной причиной моей проблемы.