2012-02-22 2 views

ответ

12

С class_eval вы можете сделать более динамичные вещи:

>> met = "hello" #=> "hello" 
>> String.class_eval "def #{met} ; 'hello' ; end" #=> nil 
>> "foo".hello #=> "hello" 
11

class_eval сделать концептуально класс повторного открытия (или обезьяны заплаток). В основном существуют синтаксические различия. Если вы передадите строку в class_eval (как в примере Майкла), у вас в основном такой же синтаксис внутри строки, как в class String; ... end. Если передать блок: String.class_eval { ... } он сравнивает следующим образом:

  • внутри class_eval блочные внешние локальные переменные видны
  • внутри вновь класс внешних локальных переменных не видны
  • внутри class_eval вы не можете присвоить константы и переменные класса контекстных к классу
  • внутри вновь открыт класс вы МОЖЕТЕ

было бы интересно узнать другие различия

0

Другие ответы хороши. Хотите добавить, что class_eval можно использовать, если вы хотите, чтобы ссылочный класс не был его константой или не исправлял конкретный объект.

например.

huh = String 
class huh 
end 
SyntaxError: (eval):2: class/module name must be CONSTANT 

huh.class_eval <<-eof 
def mamma 
puts :papa 
end 
eof 

"asdff".mamma 
=> papa 

Вы можете использовать class_eval для исправления конкретного объекта без affectin всего корневого класса.

obj = "asd" 
obj.singleton_class.class_eval <<-eof 
def asd 
puts "gah" 
end 
undef_method :some_method 

выше такой же, как:

class << obj 
    ... 
end 

instance_eval будут иметь различное поведение с помощью некоторого использования.

Я нахожу этот вопрос интересный: How to monkey patch a ruby class inside a method

Также были вопросы о instance_eval против class_eval, но у меня нет под рукой ссылку.