Можно ли получить все собственные классы в Ruby? - PullRequest
13 голосов
/ 19 октября 2011

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

ObjectSpace.each_object(Module).to_a

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

Я пытался

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

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

Ответы [ 3 ]

2 голосов
/ 06 ноября 2011

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

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

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

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

1 голос
/ 14 декабря 2011

Начиная с MRI 1.9, перечисление собственного класса, похоже, не поддерживается.Как следствие (полу), не существует 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-м собственным классам,
  • методовпринадлежит 2-му, 3-му, ... собственным классам.
1 голос
/ 26 октября 2011

Я сомневаюсь, что это то, что вы хотите, но он должен возвращать все собственные классы:

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

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

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

...