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 eval
ing 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
setsself
to whateverobj
is in the given block, which in my case is the instance ofClass
that isExample
(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
toObject
- The "current class" to
Object.singleton_class
Object.class_eval &block
sets:self
toObject
- 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 theModule
orClass
instance as bothklass
andself
instance_eval
passes the object's singleton class asklass
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
:
block.self = self;
This sets the
self
of the block to the receiver.cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
The
cref
is a linked list
which specifies the "current class", which is used fordef
,undef
andalias
, as well
as constant and class variable lookups.That line basically sets the
cref
tounder
.Finally:
When called from
module_eval
,under
will be theClass
orModule
instance.When called from
instance_eval
,under
will be the singleton class ofself
.
Related Topics
Difference Between Gemfile and Gemfile.Lock in Ruby on Rails
Ignoring Gem Because Its Extensions Are Not Built
How to Use Gem to Install Rails on Ubuntu
Rails Sends 0 Byte Files Using Send_File
Mavericks, Rbenv, Your Ruby Version Is 2.0.0, But Your Gemfile Specified 2.1.1
Execute a Sudo Command in Ruby on Rails App
Rvm Warning! Path Is Not Properly Set Up
Fork Child Process with Timeout and Capture Output
Are Crlf Lines Ok in a Rails Project Deployed on Linux
Error Sudo: Gem: Command Not Found
Has Anyone Tried Installing Ruby & Rubygems from Source on Ubuntu (Preferably Ubuntu 9)
Can't Install Rails on MAC Os Catalina
Rvm 'Not Found' After Successful Usage and a Few Days Later
Limit Space and Memory Used by Imagemagick