Я читаю раздел "Метапрограммирование" в "Программирование Ruby 1.9", и мне трудно понять, что происходит внутри между class_eval
/class_exec
и instance_eval
/instance_exec
.
Итак, в первую очередь, я понимаю, что def
добавляет метод в таблицу методов self
(объект класса):
class A
puts self # => A
def foo; 42; end # added to the method table of self, so becomes an instance method
end
A.new.foo # => 42
И если мы используем class_eval
, мы получим то же поведение:
A.class_eval do
puts self # => A
def bar; 42; end # same as above
end
A.new.bar # => 42
Но как-то в случае instance_eval
все по-другому:
A.instance_eval do
puts self # => A
def baz; 42; end # added to the method table of an anonymous
# singleton class of self, so becomes a class method
end
puts A.baz # => 42
s = 'string'
s.instance_eval do ... end # same behavior, so now def creates an instance method
Итак, я понимаю функциональную разницу между class_eval
и instance_eval
.
Но контексты внутри блоков class_eval
и instance_eval
выглядят одинаково для меня - в частности, self
указывает на один и тот же объект, а local_variables
- то же самое. Итак, что происходит внутри блоков (внутренне), что делает def
действовать иначе?
Есть ли какая-то документация, которую я мог бы прочитать? RDoc для instance_eval и class_eval не помогает. Глядя на источник, instance_eval, кажется, настроил объект одноэлементного класса, тогда как class_eval нет - но разве это отличие видимо вне кода C, на уровне Ruby?