ruby – class_eval vs instance_eval

前端之家收集整理的这篇文章主要介绍了ruby – class_eval vs instance_eval前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
class_eval和amp;有什么区别吗? instance_eval工作除了def?在class_eval块内部,def定义了类本身的方法(即实例方法),而在instance_eval中,def定义了类的本征类的方法(即类方法). AFAIK所有其他功能在两种情况下都相同(例如,define_method,attr_accessor,class<< self; end,define constants).这是真的吗? 答案是:def,undef和别名对class_eval和instance_eval有不同的上下文.

解决方法

长话短说:

>(object = Object.new).instance_eval& block sets:

>自我反对
>“当前班级”到object.singleton_class

> Object.class_eval& block sets:

>自我对象
>对象的“当前类”

“当前类”用于def,undef和别名,以及常量和类变量查找.

现在,我们来看看实现细节.

以下是在C中实现module_evalinstance_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 self) {
    VALUE klass;
    if (SPECIAL_CONST_P(self)) { klass = Qnil; }
    else { klass = rb_singleton_class(self); }
    return specific_eval(argc,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值.

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

yield_under中有两个重要的行:

> block.self = self;

这将块的自身设置为接收器.
> cref = vm_cref_push(th,under,NOEX_PUBLIC,blockptr);

cref是一个链表
它指定了“当前类”,用于def,undef和别名
作为常量和类变量查找.

该线基本上将cref设置为低于.

最后:

>从module_eval调用时,下面将是Class或Module实例.>从instance_eval调用时,下面将是单例类自.

猜你在找的Ruby相关文章