Можно ли получить все предметы в 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 для модулей и классов (или всех объектов, если я хочу пережевывать процессор), но это кажется немного хакерским.
Ответы
Ответ 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.