Class_eval vs instance_eval

Is there any difference in how class_eval and instance_eval work except def ? Inside class_eval the def block defines a method for the class itself (i.e. the instance method), and inside instance_eval def defines a method for the eigenclass class (i.e. the class method). AFAIK all other functions work the same in both cases (for example, define_method , attr_accessor , class << self; end , defining constants). It's true?

Answer : def , undef and alias have different contexts for class_eval and instance_eval .

+7
source share
2 answers

In short:

  • Object.instance_eval &block sets:
  • Object.class_eval &block sets:
    • self to Object
    • "Current class" for Object

The "current class" is used for def , undef and alias , as well as to search for class constants and variables.


Now let's look at the implementation details.

Here's how module_eval and instance_eval in C:

 VALUE rb_mod_module_eval(int argc, VALUE *argv, VALUE mod) { return specific_eval(argc, argv, mod, mod); } VALUE rb_obj_instance_eval(int argc, VALUE *argv, VALUE self) { VALUE klass; if (SPECIAL_CONST_P(self)) { klass = Qnil; } else { klass = rb_singleton_class(self); } return specific_eval(argc, argv, klass, self); } 

Both call specific_eval , which takes the following arguments: int argc , VALUE *argv , VALUE klass and VALUE self .

Note that:

  • module_eval passes an instance of Module or Class as klass and self
  • instance_eval passes a singleton class object as klass

If a block is specified, specific_eval will call yield_under , which takes the following arguments: VALUE under , VALUE self and VALUE values .

 if (rb_block_given_p()) { rb_check_arity(argc, 0, 0); return yield_under(klass, self, Qundef); } 

There are two important lines in yield_under :

  1. block.self = self;

    This sets the self part of the block to the receiver.

  2. cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);

    cref is a linked list that defines the "current class", which is used for def , undef and alias , as well as to search for class constants and variables.

    This line basically sets cref under .

    Finally:

    • When called from module_eval , under will be an instance of Class or Module .

    • When called from instance_eval , under will be a single self class.

+13
source

instance_eval allows you to directly access instance instances of an instance and use self as a reference to the instance.

0
source

All Articles