class String
def hello
"world"
end
end
String.class_eval {
def world
"hello"
end
}
"a".world
=> "hello"
"b".hello
=> "world"
Кажется, что они делают то же самое - добавление метода к существующему классу. Итак, какая разница?
class String
def hello
"world"
end
end
String.class_eval {
def world
"hello"
end
}
"a".world
=> "hello"
"b".hello
=> "world"
Кажется, что они делают то же самое - добавление метода к существующему классу. Итак, какая разница?
С помощью class_eval
вы можете делать более динамичные вещи:
>> met = "hello" #=> "hello"
>> String.class_eval "def #{met} ; 'hello' ; end" #=> nil
>> "foo".hello #=> "hello"
class_eval делать концептуально повторное открытие класса (или переключение обезьян). В основном существуют синтаксические различия. Если вы передадите строку в class_eval
(как в примере Майкла), вы в основном используете тот же синтаксис внутри строки, что и в class String; ... end
. Если вы передаете блок: String.class_eval { ... }
, он сравнивается следующим образом:
Было бы интересно узнать другие различия
Другие ответы хороши. Хотите добавить, что 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
для исправления определенного объекта без влияния на весь корневой класс.
obj = "asd"
obj.singleton_class.class_eval <<-eof
def asd
puts "gah"
end
undef_method :some_method
Вышеуказанное значение равно:
class << obj
...
end
instance_eval
будет иметь несколько другое поведение при некотором использовании.
Я нахожу этот вопрос и ответы интересным: Как обезглавить патч рубинового класса внутри метода
Также были вопросы о instance_eval
vs class_eval
, но у меня нет ссылки.