Is there any difference in how class_eval
& instance_eval
work except def
? Inside class_eval
block def
defines method to class itself (i.e. instance method) and inside instance_eval
def
defines method to the eigenclass of the class (i.e. class method). AFAIK all other features work identically in both cases (e.g. define_method
, attr_accessor
, class << self; end
, defining constants). Is it true?
Answer is: def
, undef
and alias
have different contexts for class_eval
and instance_eval
.
Long story short:
Object.instance_eval &block
sets:self
toObject
Object.singleton_class
Object.class_eval &block
sets:self
toObject
Object
The "current class" is used for
def
,undef
andalias
, as well as constant and class variable lookups.Now, let's have a look at the implementation details.
Here's how
module_eval
andinstance_eval
are implemented in C:Both call
specific_eval
, which takes the following arguments:int argc
,VALUE *argv
,VALUE klass
andVALUE self
.Note that:
module_eval
passes theModule
orClass
instance as bothklass
andself
instance_eval
passes the object's singleton class asklass
If given a block,
specific_eval
will callyield_under
, which takes the following arguments:VALUE under
,VALUE self
andVALUE values
.There are two important lines in
yield_under
:block.self = self;
This sets the
self
of the block to the receiver.cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
The
cref
is a linked list which specifies the "current class", which is used fordef
,undef
andalias
, as well as constant and class variable lookups.That line basically sets the
cref
tounder
.Finally:
When called from
module_eval
,under
will be theClass
orModule
instance.When called from
instance_eval
,under
will be the singleton class ofself
.