2010-07-03 14 views
17

Ruby'de metaprogramlama harikadır çünkü prototip tabanlı programlamayı taklit etmek ve bazı problemlere uygulanabilirliklerini test etmek için prototip çözümler yazmak için sürekli olarak kullanıyorum.Yakut tekil yöntemler ile (class_eval, define_method) vs (örnek_eval, define_method)

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

ve

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

kod iki sürümü bir tekil yöntem tanımlamak ve henüz gelmediler: aşağıdaki kod parçaları arasındaki köklü bir fark olup olmadığını yüzden bilmek istiyorum tek bir yöntem tanımlamak için (class_eval, define_method) kombinasyonu üzerinde (instance_eval, define_method) kombinasyonu seçmek için beni zorladı herhangi bir şeye karşı yukarı ve ikisi arasında bazı temel fark olup olmadığını merak ediyorum.

+1

Not Yukarıdaki yapmanın en iyi yolu basitçe olduğunu 'define_singleton_method (: method_name) do ... Sonu '

Bu çeşidin eigenclass bir sınıf yöntemidir –

cevap

21

define_method için fark yok. Ancak, def'u kullandığınızda bir fark vardır.

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 

Neden def ve define_method arasındaki davranış farkı? define_method bir yöntem çağrısıdır ve bu nedenle self üzerinde çalışmaktadır. Hem instance_eval hem de class_eval'daki self aynıdır - alıcıdır (o'nun eigenclassı).

Ancak, def farklı davranır,üzerinde değil, default definee üzerinde çalışmaz. class_eval durumunda, default definee, self ile aynıdır, ancak instance_eval için self'un meta sınıfıdır.

Yukarıda tanımlanan test2 yöntemine nasıl erişiriz? Test2, o'ndaki eigenclassın meta sınıfında tanımlanan bir örnek metodu olmalıdır.

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