Как динамически вызывать классы, не используя eval? - PullRequest
0 голосов
/ 03 февраля 2009

Можно ли избавиться от оператора eval ниже? Приведенный ниже код отфильтровывает все классы, которые являются производными от типа BaseClass. После этого создаются эти классы и вызывается метод 'hello'.

module MySpace

  class BaseClass
    def hello; print "\nhello world"; end
  end

  class A<BaseClass
    def hello; super; print ", class A was here"; end
  end

  class B<BaseClass
    def hello; super; print ", I'm just a noisy class"; end
  end

  MySpace.constants.each do | e |
    c=eval(e)
    if c < BaseClass
      c.new.hello
    end
  end

end

Итак, после выполнения вы получите:

Привет, мир, я просто шумный класс
Привет, мир, класс А был здесь

Я думаю, что ненужное использование eval - зло. И я не уверен, обязательно ли здесь использование eval . Есть ли более разумный способ динамического вызова всех классов из типа "BaseClass"?

Ответы [ 3 ]

4 голосов
/ 03 февраля 2009
c = MySpace.const_get(e)
0 голосов
/ 03 февраля 2009

eval - единственный известный мне способ превратить строку в константу. Это даже способ, которым рельсы делают это: http://api.rubyonrails.com/classes/Inflector.html#M001638

Странно то, что константы возвращают строки.

0 голосов
/ 03 февраля 2009

Вы смотрели на class_eval вместо?

------------------------------------------------------ Module#class_eval
     mod.class_eval(string [, filename [, lineno]])  => obj
     mod.module_eval {|| block }                     => obj
------------------------------------------------------------------------
     Evaluates the string or block in the context of _mod_. This can be
     used to add methods to a class. +module_eval+ returns the result of
     evaluating its argument. The optional _filename_ and _lineno_
     parameters set the text for error messages.

        class Thing
        end
        a = %q{def hello() "Hello there!" end}
        Thing.module_eval(a)
        puts Thing.new.hello()
        Thing.module_eval("invalid code", "dummy", 123)

    produces:

        Hello there!
        dummy:123:in `module_eval': undefined local variable
            or method `code' for Thing:Class
...