Это причудливое поведение имеет смысл, если вы посмотрите на instance_eval
в контексте экземпляров (что является его основной целью).
class A
end
a = A.new
a.instance_eval do
def foo
end
end
Где находится foo
? Единственное разумное место, где я могу думать «синглтон класс с, а на самом деле это правда
a.method(:foo).owner == a.singleton_class
# true
Так что это демонстрирует правило
def
внутри instance_eval
определяет метод в self
» a
одноплодной класса s ,
, который полностью соответствует тому, что вы видели.
A.instance_eval do
# defines method in A's singleton class!
def method; end
end
Так почему же define_method
ведут себя по-другому? Потому что в отличие от def
это метод ! Так что это
A.instance_eval do
define_method(:foo) {}
end
действительно просто
A.define_method(:foo) {}
который является метапрограммированием способ создания нормальных методов экземпляра. Эта несогласованность может показаться раздражающей, но снова взгляните на случай для нормальных случаев, и вы поймете, почему def
и define_method
не могут быть последовательными. Это
a.instance_eval do
define_method(:foo) {}
end
действительно просто
a.define_method(:foo) {}
который нонсенс
NoMethodError: undefined method `define_method' for #<A:0x00008>
Если вы хотите, чтобы ваша боль болела, найдите концепцию «default definee» (то есть «вещь, где' def' заканчивается методом put »), а какой из методов' * _eval' изменяется сам ', который изменяет значение по умолчанию, которое меняет и то, и какой из методов' define _ * _ method 'соблюдает дефолт по умолчанию, а какие нет. Это довольно беспорядок. –
http://yugui.jp/articles/846 –