How to understand the difference between class_eval() and instance_eval()?

前端 未结 5 1834
终归单人心
终归单人心 2020-12-02 04:47
Foo = Class.new
Foo.class_eval do
  def class_bar
    \"class_bar\"
  end
end
Foo.instance_eval do
  def instance_bar
    \"instance_bar\"
  end
end
Foo.class_bar            


        
5条回答
  •  Happy的楠姐
    2020-12-02 05:16

    The other answer is correct, but allow me to go in depth a little.

    Ruby has a number of different kinds of scope; six according to wikipedia, though detailed formal documentation seems to be lacking. The kinds of scope involved in this question are, not surprisingly, instance and class.

    The current instance scope is defined by the value of self. All unqualified method calls are dispatched to the current instance, as are any references to instance variables (which look like @this).

    However, def is not a method call. The target for methods created by def is the current class (or module), which can be found with Module.nesting[0].

    Let's see how the two different eval flavors affect these scopes:

    String.class_eval { [self, Module.nesting[0]] } => [String, String] String.instance_eval { [self, Module.nesting[0]] } => [String, #]

    In both cases, the instance scope is the object on which *_eval is called.

    For class_eval, the class scope also becomes the target object, so def creates instance methods for that class/module.

    For instance_eval, the class scope becomes the singleton class (aka metaclass, eigenclass) of the target object. Instance methods created on the singleton class for an object become singleton methods for that object. Singleton methods for a class or module are what are commonly (and somewhat inaccurately) called class methods.

    The class scope is also used to resolve constants. Class variables (@@these @@things) are resolved with class scope, but they skip over singleton classes when searching the module nesting chain. The only way I have found to access class variables in singleton classes is with class_variable_get/set.

提交回复
热议问题