How to Understand the Difference Between Class_Eval() and Instance_Eval()

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

As the documentation says, class_eval evaluates the string or block in the context of the Module or Class. So the following pieces of code 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 has been reopened and a new method defined. That method is available across all instances of the class, so:

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

class_eval has a number of advantages over simply reopening the class. Firstly, you can easily call it on a variable, and it's clear what your intent is. Another advantage is that it will fail if the class doesn't exist. So the example below will fail as Array is spelt incorrectly. If the class was simply reopened, it would succeed (and a new incorrect Aray class would be defined):

Aray.class_eval do
include MyAmazingArrayExtensions
end

Finally class_eval can take a string, which can be useful if you're doing something a little more nefarious...

instance_eval on the other hand evaluates code against a single object instance:

confusing = "This Is Confusing"
confusing.instance_eval do
def lowercase
self.downcase
end
end

confusing.lowercase
=> "this is confusing"
"The Smiths on Charlie's Bus".lowercase
NoMethodError: undefined method ‘lowercase’ for "The Smiths on Charlie's Bus":String

So with instance_eval, the method is only defined for that single instance of a string.

So why does instance_eval on a Class define class methods?

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

"This Is Confusing".class
=> String

String.class
=> Class

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

Difference between class_eval and instance_eval in a module

In your example there is no difference.

> Foo1.instance_eval { puts self } 
Foo1

> Foo1.class_eval { puts self }
Foo1

The instance of a class is the class itself. instance_eval gives you nothing "extra" here. But if you use it on an instance of a class, then you get different behaviour. I.e. Foo1.new.instance_eval ....

See here for a good explanation:

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

Why does instance_eval() define a class method when called on a class?

x.instance_eval changes your context so self evaluates to x.

This allows you to do many things, including defining instance variables and instance methods but only for x.

 x = Object.new
y = Object.new

# define instance variables for x and y
x.instance_eval { @var = 1 }
y.instance_eval { @var = 2 }

# define an instance method for all Objects
class Object
def var
@var
end
end

x.var #=> 1
y.var #=> 2

Ruby lets you define instance methods for an object in a couple places. Normally,
one defines them in a class, and those instance methods are shared among all instances
of that class (like def var above).

However, we can also define an instance method for just a single object:

# here's one way to do it
def x.foo
"foo!"
end
# here's another
x.instance_eval do
# remember, in here self is x, so bar is attached to x.
def bar
"bar!"
end
end

Even though x and y have the same class, they don't share these methods, since they were only defined for x.

x.foo #=> "foo!"
x.bar #=> "bar!"
y.foo #=> raises NoMethodError
y.bar #=> raises NoMethodError

Now in ruby, everything's an object, even classes. Class methods are just instance methods
for that class object.

# we have two ways of creating a class:
class A
end
# the former is just syntatic sugar for the latter
B = Class.new

# we have do ways of defining class methods:

# the first two are the same as for any other object
def A.baz
"baz!"
end
A.instance_eval do
def frog
"frog!"
end
end

# the others are in the class context, which is slightly different
class A
def self.marco
"polo!"
end
# since A == self in here, this is the same as the last one.
def A.red_light
"green light!"
end

# unlike instance_eval, class context is special in that methods that
# aren't attached to a specific object are taken as instance methods for instances
# of the class
def example
"I'm an instance of A, not A itself"
end
end
# class_eval opens up the class context in the same way
A.class_eval do
def self.telegram
"not a land shark"
end
end

Note again, that all these methods are A-specific, B doesn't get access to any of them:

A.baz #=> "baz!"
B.telegram #=> raises NoMethodError

The important thing to take away from here is that
class methods are just instance methods of an object of class Class

Whats the difference between class_eval and class className?

class_eval doesn't really have anything to do with class << className.

A.class_eval do
...
end

is equivalent to

class A
...
end

with a few differences. class_eval uses a block (or a string, but ignoring that for the moment) which means it closes over the containing lexical scope. In other words you can use local variables from the surrounding scope. The common class block introduces a brand new scope. Likewise you can create the block and pass it to many different class_eval's, and the body of the block will be executed in the context of the class you are calling class_eval on.

class << className opens the singleton class of className, allowing you to define class methods.

class << A
def foo
...
end
end

Is the same as

def A.foo
...
end

Note that they are oly class methods if A happens to be a class (almost) all objects in ruby have singleton classes and you can define methods for them using either of those two syntaxes. The advantage of class << obj is mainly if you're defining many singleton methods in one go.

What's the difference between eval and class_eval?

In eval, you cannot choose where to run the code, it is always in your current context. Also, it only accepts a string of code. So if you have a method definition as a string, you can only use it by evaling the string in a class body.

In module_eval/class_eval and instance_eval the code can be a string or a block, and you explicitly select the receiver (respectively the module as part of some inheritance chain, or the instance itself).

Notice that some_obj.instance_eval(&blk) is essentially the same as some_obj.singleton_class.class_eval(&blk)

Ruby's def and instance_eval vs. class_eval

I think your confusion comes from the fact that def does not depend on the current self, you might think about it as being a "current class" that has it's own rules.

Following your examples:

class A
# defs here go to A
puts self # => A
class << self
#defs here go to A's eigenclass
end
end

A.class_eval do
#defs here go to A
end

A.instance_eval do
#defs here go to A's eigenclass
end

s = "Hello World"

class << s
#defs here go to s's eigenclass
end

Here's the portion of the chapter that talks about the issue and it's pretty clear about the behaviour

class_eval and instance_eval both set
self for the duration of the block.
However, they differ in the way they
set up the environment for method
definition. class_eval sets things up
as if you were in the body of a class
definition, so method definitions will
define instance methods In contrast,
calling instance_eval on a class acts
as if you were working inside the
singleton class of self. Therefore,
any methods you define will become
class methods.

The only thing I think is worth adding is that you can call instance_eval in any object, not just classes, and the behaviour doesn't change but has different consequences.

Some relevant reading:

Ruby: instance_eval and class_eval method definitions

Chapter 4 of this most excelent series

Difference between instance_eval and singleton method

The metaprogramming tool instance_eval does the same thing right? Defining a method for a particular instance?

No. instance_eval has nothing whatsoever to do with defining methods. It evaluates a block in the context of the receiver. Normally, blocks are lexically scoped, including self, a block that is evaluated using instance_eval is evaluated with self bound to the receiver of the message.

one = Object.new
two = Object.new

def one.my_eval; yield end

instance_variables
# => []

one.my_eval { @ivar_one = 1 }

one.instance_variables
# => []

instance_variables
# => [:@ivar_one]

two.instance_eval { @ivar_two = 2 }

two.instance_variables
# => [:@ivar_two]

So what is really the difference?

They are completely unrelated. It doesn't really make sense to ask about the difference between two unrelated things.

Difference between instance_eval and class self?

class << obj sets self to whatever obj is in the given block, which in my case is the instance of Class that is Example (this is where I'm probably wrong);

No, class << obj opens up the singleton class of obj. As you correctly pointed out, inside of a class declaration, self refers to the class itself, so, in this case, the "inner" self (i.e. the one being passed to puts) refers to the singleton class of Example.

class_eval vs instance_eval

Long story short:

  • Object.instance_eval &block sets:

    • self to Object
    • The "current class" to Object.singleton_class
  • Object.class_eval &block sets:

    • self to Object
    • The "current class" to Object

The "current class" is used for def, undef and alias, as well as constant and class variable lookups.


Now, let's have a look at the implementation details.

Here's how module_eval and instance_eval are implemented in C:

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);
}

Both call specific_eval, which takes the following arguments: int argc, VALUE *argv, VALUE klass and VALUE self.

Note that:

  • module_eval passes the Module or Class instance as both klass and self
  • instance_eval passes the object's singleton class as klass

If given a block, specific_eval will call yield_under, which takes the following arguments: VALUE under, VALUE self and VALUE values.

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

There are two important lines in yield_under:

  1. block.self = self;

    This sets the self of the block to the receiver.

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

    The cref is a linked list
    which specifies the "current class", which is used for def, undef and alias, as well
    as constant and class variable lookups.

    That line basically sets the cref to under.

    Finally:

    • When called from module_eval, under will be the Class or Module
      instance.

    • When called from instance_eval, under will be the singleton class of
      self.



Related Topics



Leave a reply



Submit