[英]class_eval vs instance_eval
Is there any difference in how class_eval
& instance_eval
work except def
? 除了
def
之外, class_eval
和instance_eval
工作方式有什么不同吗? Inside class_eval
block def
defines method to class itself (ie instance method) and inside instance_eval
def
defines method to the eigenclass of the class (ie class method). 在
class_eval
块内部, def
定义了类本身的方法(即实例方法),而在instance_eval
def
定义了类的本征类的方法(即类方法)。 AFAIK all other features work identically in both cases (eg define_method
, attr_accessor
, class << self; end
, defining constants). AFAIK所有其他功能在两种情况下都相同(例如
define_method
, attr_accessor
, class << self; end
, attr_accessor
constants)。 Is it true? 这是真的吗?
Answer is : def
, undef
and alias
have different contexts for class_eval
and instance_eval
. 答案是 :
def
, undef
和alias
对class_eval
和instance_eval
有不同的上下文。
Long story short: 长话短说:
Object.instance_eval &block
sets: Object.instance_eval &block
集:
self
to Object
self
Object
Object.singleton_class
Object.singleton_class
的“当前类” Object.class_eval &block
sets: Object.class_eval &block
集:
self
to Object
self
Object
Object
Object
的“当前类” The "current class" is used for def
, undef
and alias
, as well as constant and class variable lookups. “当前类”用于
def
, undef
和alias
,以及常量和类变量查找。
Now, let's have a look at the implementation details. 现在,我们来看看实现细节。
Here's how module_eval
and instance_eval
are implemented in C: 以下是在C中实现
module_eval
和instance_eval
方式:
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
. 两者都调用
specific_eval
,它采用以下参数: int argc
, VALUE *argv
, VALUE klass
和VALUE self
。
Note that: 注意:
module_eval
passes the Module
or Class
instance as both klass
and self
module_eval
将Module
或Class
实例作为klass
和 self
传递 instance_eval
passes the object's singleton class as klass
instance_eval
将对象的单例类作为klass
传递 If given a block, specific_eval
will call yield_under
, which takes the following arguments: VALUE under
, VALUE self
and VALUE values
. 如果给定一个块,
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);
}
There are two important lines in yield_under
: yield_under
有两个重要的行:
block.self = self;
This sets the self
of the block to the receiver. 这将块的
self
设置为接收器。
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
The cref
is a linked list which specifies the "current class", which is used for def
, undef
and alias
, as well as constant and class variable lookups. cref
是一个链接列表 ,它指定“当前类”,用于def
, undef
和alias
,以及常量和类变量查找。
That line basically sets the cref
to under
. 该线基本上将
cref
设置为under
。
Finally: 最后:
When called from module_eval
, under
will be the Class
or Module
instance. 从
module_eval
调用时, under
将是Class
或Module
实例。
When called from instance_eval
, under
will be the singleton class of self
. 从
instance_eval
调用时, under
将是self
的单例类 。
instance_eval
允许您直接访问实例的实例变量,并使用self
作为实例的引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.