长话短说:
-
Object.instance_eval &block 套:
-
Object.class_eval &block 套:
-
self 到 Object
-
Object 的“当前班级”
“当前类”用于def、undef 和alias,以及常量和类变量查找。
现在,让我们看一下实现细节。
下面是 module_eval 和 instance_eval 在 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);
}
两者都调用specific_eval,它接受以下参数:int argc、VALUE *argv、VALUE klass 和VALUE self。
注意:
-
module_eval 传递 Module 或 Class 实例作为 klass 和 self
-
instance_eval 将对象的 单例类 传递为 klass
如果给定一个块,specific_eval 将调用 yield_under,它采用以下参数:VALUE under、VALUE self 和 VALUE values。
if (rb_block_given_p()) {
rb_check_arity(argc, 0, 0);
return yield_under(klass, self, Qundef);
}
yield_under中有两行重要的:
-
block.self = self;
这会将块的self 设置为接收者。
-
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
cref 是一个链表
指定“当前类”,也用于def、undef 和alias
作为常量和类变量查找。
该行基本上将cref 设置为under。
最后: