Explain the instance_eval method in Ruby and its comparison with class_eval, rubyinstanceeval
Instance_eval Method
This BasicObject # instance_eval is a bit similar to the bind method in JS. In different cases, bind transmits this to the object, while instance_eval refers to the code block (Context Probe) input to the specified object. One is an object and the other is an object. In this way, you can access the variables in the caller object in the code block of instance_eval.
Sample Code
class MyClass def initialize @v = 1 endendobj = MyClass.newobj.instance_eval do self #=> #<MyClass:0x33333 @v=1> @v #=> 1 endv = 2obj.instance_eval { @v = v }obj.instance_eval { @v } # => 2
In addition, the instance_eval method has a twin brother: instance_exec method. It is more flexible than the former and the latter, allowing parameters to be passed in to the code block.
Sample Code
class C def initialize @x = 1 endendclass D def twisted_method @y = 2 #C.new.instance_eval { “@x: #{@x}, @y>: #{y}” } C.new.instance_exec(@y) { |y| “@x: #{@x}, @y: #{y}” } endend#D.new.twisted_method # => “@x: 1, @y: ”D.new.twisted_method # => “@x: 1, @y: 2”
Because after instance_eval is called, the caller is used as the current self, so the scope is changed to class C, and the previous scope does not take effect. If you want to access the previous @ y variable, you need to use @ y on the parameter package to escape with instance_eval. However, because instance_eval cannot carry parameters, the instance_exec method of the sibling brother is used.
Differences between instance_eval and class_eval
### Instance_eval
First, the information obtained from the name is that the caller of instance_eval must be an instance, and in the instance_eval block, self is the worker er instance itself.
obj_instance.instance_eval do self # => obj_instance # current class => obj_instance's singleton classend<!--more-->
According to this definition, if instance_eval is called on an instance, you can define the singleton_method
class Aenda = A.newa.instance_eval do self # => a # current class => a's singleton class def method1 puts 'this is a singleton method of instance a' endenda.method1#=> this is a singleton method of instance ab = A.newb.method1#=>NoMethodError: undefined method `method1' for #<A:0x10043ff70>
Similarly, because the class itself is also an instance of the Class class, instance_eval can also be used in the Class. At this time, the singleton_method of the class can be defined in it, that is, the Class function of the class.
In other words, you can use instance_eval to define the class method of the class function, which is confusing and needs to be clarified.
class AendA.instance_eval do self # => A # current class => A's singleton class def method1 puts 'this is a singleton method of class A' endendA.method1#=> this is a singleton method of class Aclass_eval
### Class_eval
Let's take a look at class_eval. The first information we can get from the name is that the caller of class_eval must be a class, and inside the class_eval block, self is the aggreger class itself.
class AendA.class_eval do self # => A # current class => Aend
According to this definition, if class_eval is called on a class, you can define the instance function instance_method of this class.
class Aenda = A.newa.method1#=> NoMethodError: undefined method `method1' for #<A:0x10043ff70>A.class_eval do self # => A # current class => A def method1 puts 'this is a instance method of class A' endenda.method1#=> this is a instance method of class A
In other words, you can use class_eval to define the instance method of the instance function, which is easy to confuse and needs to be clarified.