Подтвердить что ты не робот

Можно ли получить все предметы в Ruby?

Получение списка всех модулей в Ruby легко:

ObjectSpace.each_object(Module).to_a

Однако можно ли получить список всех eigenclasses (также известных как одноэлементные классы или метаклассы)? Или невидимые eigenclass?

Я пробовал

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

Я пытаюсь получить eigenclasses, потому что я хочу перечислить все методы, которые определены в script. Я мог бы искать все методы экземпляра, определенные модулями и классами, а затем искать методы singleton для модулей и классов (или всех объектов, если я хочу пережевывать процессор), но это кажется немного хакерским.

4b9b3361

Ответ 1

Если вы имеете в виду объекты с одноточечными методами, это должно работать.

eigens = []
ObjectSpace.each_object do |object|
  eigens << object unless object.singleton_methods.empty?
end

Если нет, не могли бы вы уточнить? Я использовал это обсуждение как ссылку:

http://www.ruby-forum.com/topic/77046

Ответ 2

Я сомневаюсь, что это то, что вы хотите, но оно должно вернуть все eigenclasses:

eigens = ObjectSpace.each_object.collect { |obj| class << obj; self; end }

Это действительно назначит массив всех eigenclasses для переменных eigens. Дело в том, что реализации Ruby, вероятно, на самом деле не создают eigenclass, если в этом нет необходимости, и этот код (я считаю) фактически создаст собственные классы даже для объектов, где он не нужен.

Если найти лучший способ очень важен, я бы подкрепил вопрос одному из разработчиков любой из реализаций Ruby (@yukihiro_matz, @evanphx, @headius, чтобы назвать несколько, которые приходят на ум). Если кто-нибудь узнает, они будут.

Ответ 3

Как и в MRI 1.9, перечисление eigenclass, похоже, не поддерживается. Как следствие (полу), нет 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)
}

Однако этот код НЕ будет перечислять

  • частные методы, принадлежащие 1-м eigenclasses,
  • принадлежащие 2-м, 3-м,... eigenclasses.