Memorize this:
|
changes self to |
changes current class to |
class_eval |
receiver |
receiver |
instance_eval |
receiver |
receiver's singleton class |
Methods defined in ruby with def
keyword (without an explicit receiver) are always defined in the "current class" (that's what Paolo Perrotta calls it in Metaprogramming Ruby; others call it "default definee")
The "current class" is something we usually don't think about because it's intuitive; inside a class definition, the current class is the class itself, so methods defined with def foo
inside a class definition become instance methods of that class.
But when you call instance_eval with the A
class being the receiver, as per the table above, you are changing the 'current class' to the receiver's singleton class; since you are defining a method with def
, it will be defined in the 'current class', which results in a 'class method' (a method defined in A's singleton class or eigenclass):
class A
end
A.instance_eval do
# the current class here is not A, but A's singleton class;
def method; end
end
However, when you define the method with define_method
, as per the table above, you are actually invoking define_method
on an implicit receiver self
; if you look at the table, self
will be the receiver A
, so it's the same as calling A.define_method
or even:
class A
define_method(:method1) {}
end
So that's why, in this case, you get an instance method, because you called define_method on the class A, and not in A's singleton class (or also called eigenclass).