CLASS_VERVS实例_VERA [英] class_eval vs instance_eval

查看:14
本文介绍了CLASS_VERVS实例_VERA的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

def之外,class_eval&;instance_eval的工作方式有什么不同?class_evaldef将方法定义为类本身(即实例方法),而instance_evaldef将方法定义为类的特征类(即类方法)。AFAIK所有其他功能在这两种情况下的工作方式相同(例如,定义常量的define_methodattr_accessorclass << self; end)。这是真的吗?

答案是defundefalias对于class_evalinstance_eval具有不同的上下文。

推荐答案

长话短说:

  • Object.instance_eval &block套:
  • Object.class_eval &block套:
    • selfObject
    • 将当前类设置为Object

"当前类"用于defundefalias以及常量和类变量查找。


现在,让我们来看看实现的详细信息。

下面介绍如何在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 *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 argcVALUE *argvVALUE klassVALUE self

请注意:

  • module_evalModuleClass实例作为klassself
  • 传递
  • instance_eval将对象的单例类作为klass
  • 传递

如果给出一个块,specific_eval将调用yield_under,它接受以下参数:VALUE underVALUE selfVALUE values

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

yield_under中有两行重要内容:

  1. block.self = self;

    这会将块的self设置为接收方。

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

    cref链表 指定当前类,也用于defundefalias 作为常量和类变量查找。

    该行基本上将cref设置为under

    最后:

    • module_eval调用时,under将为ClassModule 实例。

      /li>
    • instance_eval调用时,under将是的单例类 self

这篇关于CLASS_VERVS实例_VERA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆