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

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 #=> undefined method 'class_bar' for Foo:Class Foo.new.class_bar #=> "class_bar" Foo.instance_bar #=> "instance_bar" Foo.new.instance_bar #=> undefined method 'instance_bar' for #<Foo:0x7dce8> 

Just based on the name of the methods I would expect class_eval to allow you to add a class method to Foo and instance_eval so that you can add an instance method to Foo. But they seem to be doing the opposite .

In the above example, if you call class_bar in the Foo class, you get an undefined method error, and if you call the instance string of the instance returned by Foo.new, you also get an undefined method error. Both errors seem to contradict the intuitive understanding of what class_eval and instance_eval should do.

What is the difference between these methods?

Documentation for class_eval :

mod.class_eval (string [, filename [, lineno]]) => obj

Computes a string or block in a fashion context. This can be used to add methods to the class.

Documentation for instance_eval :

obj.instance_eval {| | block} => obj

Computes a string containing the Ruby source code or the given block, in the context of the receiver (OBJ). To set the context, the self variable is set to obj while the code executes, issuing the code access to the objs instance variables.

+45
ruby class-method
May 22 '09 at 23:32
source share
4 answers

As the documentation says, class_eval evaluates a row or block in the context of a module or class. Thus, the following code fragments are equivalent:

 class String def lowercase self.downcase end end String.class_eval do def lowercase self.downcase end end 

In each case, the String class was reopened and a new method defined. This method is available for all instances of the class, therefore:

 "This Is Confusing".lowercase => "this is confusing" "The Smiths on Charlie Bus".lowercase => "the smiths on charlie bus" 

class_eval has several advantages over just reopening a class. First, you can easily call it a variable, and itโ€™s clear what your intentions are. Another advantage is that it will not work if the class does not exist. Thus, the example below will not be executed, as Array will be incorrectly specified. If the class was simply reopened, it will succeed (and a new invalid Aray class will be defined):

 Aray.class_eval do include MyAmazingArrayExtensions end 

Finally, class_eval can take a line that might be useful if you are doing something more vile ...

instance_eval , on the other hand, evaluates the code for one instance of an object:

 confusing = "This Is Confusing" confusing.instance_eval do def lowercase self.downcase end end confusing.lowercase => "this is confusing" "The Smiths on Charlie Bus".lowercase NoMethodError: undefined method 'lowercase' for "The Smiths on Charlie Bus":String 

So, with instance_eval method is defined only for this single row instance.

So why does instance_eval in Class define class methods?

Just like "This Is Confusing" and "The Smiths on Charlie Bus" are instances of String , Array , String , Hash , and all other classes themselves are instances of Class . You can verify this by calling #class on them:

 "This Is Confusing".class => String String.class => Class 

Therefore, when we call instance_eval , it does the same in the class as it does on any other object. If we use instance_eval to define a method for a class, it will define a method only for that instance of the class, and not for all classes. We can call this method a class method, but it is just an instance method for this particular class.

+75
May 23 '09 at
source share
โ€” -

The other answer is correct, but let me go a little deeper.

Ruby has several different areas; six according to wikipedia , although there seems to be no formal documentary documentation. Uncertainly, the types of coverage associated with this issue are instance and class .

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

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

See how two different tastes of eval affect these areas:

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

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

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

For instance_eval the scope of the class becomes the singleton class (aka metaclass, eigenclass) of the target. Instance methods created in a singleton class for an object become single-point methods for this object. Singleton methods for a class or module are what are usually (and somewhat inaccurate) called class methods .

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

+16
Aug 23 '09 at 10:08
source share

I think you got it wrong. class_eval adds a method to the class, so all instances will have this method. instance_eval will add a method to only one specific object.

 foo = Foo.new foo.instance_eval do def instance_bar "instance_bar" end end foo.instance_bar #=> "instance_bar" baz = Foo.new baz.instance_bar #=> undefined method 
+5
May 22, '09 at 23:50
source share

instance_eval effectively creates a singleton method for the instance of the object in question. class_eval will create a normal method in this context of the class, accessible to all objects of this class.

Here's a link to singleton and singleton pattern methods (non-ruby)

+3
May 23 '09 at
source share



All Articles