我了解instance_evalclass_eval之间的基本区别。我在玩耍时发现的是涉及attr_accessor的奇怪内容。这是一个例子:

A = Class.new
A.class_eval{ attr_accessor :x }

a = A.new
a.x = "x"
a.x
=> "x"  # ... expected

A.instance_eval{ attr_accessor :y }

A.y = "y"
=> NoMethodError: undefined method `y=' for A:Class

a.y = "y"
=> "y"      # WHATTT?

怎么回事:
  • instance_eval不在我们的A类(对象)的访问器上
  • 然后将其实际上添加到A的实例上?
  • 最佳答案

    首先,您的理解(或直觉)是正确的,#instance_eval#class_eval内部定义的方法不相同

    A = Class.new
    
    A.instance_eval { def defined_in_instance_eval; :instance_eval; end }
    A.class_eval { def defined_in_class_eval; :class_eval; end }
    
    A.new.defined_in_class_eval # => :class_eval
    A.defined_in_instance_eval # => :instance_eval
    

    旁注:虽然selfinstance_eval中的class_eval相同,但的默认定义是不同的,请参阅http://yugui.jp/articles/846

    真正的窍门是Module#attr_accessor本身,看一下它的定义:
    http://rxr.whitequark.org/mri/source/vm_method.c#620

    它不使用def,不读取上下文,self或默认定义。它只是“手动”将方法插入模块。这就是为什么结果违反直觉的原因。

    关于ruby - 带有attr_accessor的类上的Ruby instance_eval,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14428531/

    10-08 23:08