Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby singleton methods with (class_eval, define_method) vs (instance_eval, define_method)

Metaprogramming in ruby is great because I constantly use it to emulate prototype based programming and quickly write prototype solutions to some problems to test their viability. So I would like to know if there is any essential difference between the following pieces of code:

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

and

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

Both versions of the code define a singleton method and I haven't yet come up against anything that has forced me to choose the (instance_eval, define_method) combination over the (class_eval, define_method) combination to define a singleton method and I'm wondering if there is some essential difference between the two.

like image 934
David K. Avatar asked Jul 03 '10 08:07

David K.


1 Answers

No difference for define_method. But there is a difference when you use 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

Why the difference in behaviour between def and define_method ? define_method is a method call and so operates on the self in the eval context. The self in both instance_eval and class_eval is the same - it is the receiver (the eigenclass of o).

However def behaves differently, it does not operate on the self but instead on the default define. In the case of class_eval the default definee is the same as self but for instance_eval it is instead the metaclass of self.

How do we access the test2 method defined above? test2 must be an instance method defined on the metaclass of the eigenclass of o.

It is a class method on the eigenclass of o:

class << o; test2; end #=> :test2
like image 176
horseyguy Avatar answered Nov 04 '22 08:11

horseyguy