Подтвердить что ты не робот

Ruby Singleton методы с (class_eval, define_method) vs (instance_eval, define_method)

Метапрограммирование в рубине велико, потому что я постоянно использую его для эмуляции прототипов на основе программирования и быстрого написания прототипов решения некоторых проблем, чтобы проверить их жизнеспособность. Поэтому я хотел бы знать, есть ли существенное различие между следующими фрагментами кода:

(class << some_object; self; end).class_eval do
  define_method(:method_name) do ... method body ... end
end

и

(class << some_object; self; end).instance_eval do
  define_method(:method_name) do ... method body ... end
end

Обе версии кода определяют одноэлементный метод, и я еще не сталкивался с чем-либо, что вынудило меня выбрать комбинацию (instance_eval, define_method) по сравнению с комбинацией (class_eval, define_method) для определения метода singleton, и мне интересно, между ними существует существенное различие.

4b9b3361

Ответ 1

Нет разницы для define_method. Но есть разница, когда вы используете def.

o = Object.new  

# class_eval example
class << o; self; end.class_eval { def test1;  :test1; end  }
o.test1 #=> test1

# instance_eval example
class << o; self; end.instance_eval { def test2; :test2; end }
o.test2 #=> NoMethodError

Почему разница в поведении между def и define_method? define_method является вызовом метода и, таким образом, действует на self в контексте eval. self как в instance_eval и в class_eval - одно и то же - это получатель (собственный класс o).

Однако def ведет себя по-разному, он работает не на самом self а на default define по default define. В случае class_eval определение по default definee - это то же самое, что и self но для instance_eval это метакласс self.

Как нам получить доступ к методу test2 определенному выше? test2 должен быть методом экземпляра, определенным в метаклассе собственного класса o.

Это метод класса на собственном классе o:

class << o; test2; end #=> :test2