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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With