加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – class_eval vs instance_eval

发布时间:2020-12-17 04:20:49 所属栏目:百科 来源:网络整理
导读:class_eval和amp;有什么区别吗? instance_eval工作除了def?在class_eval块内部,def定义了类本身的方法(即实例方法),而在instance_eval中,def定义了类的本征类的方法(即类方法). AFAIK所有其他功能在两种情况下都相同(例如,define_method,attr_accessor,cla
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调用时,下面将是单例类自.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读