Ruby: How Does Constant-Lookup Work in Instance_Eval/Class_Eval

Accessing Ruby Class Variables with class_eval and instance_eval

I just asked the same question to Matz during the RubyKaigi party. I was half-drunk, but he was perfectly sober, so you can take this as the definitive answer.

Anton is right - the reason why you cannot access class variables through instance_eval() is "just because". Even class_eval() shares the same issue (Matz himself wasn't totally sure about class_eval() until I told him I'd already tried it). More specifically: scope-wise, class variables are more like constants than instance variables, so switching self (as instance_eval() and class_eval() do) is not going to make any difference when it comes to accessing them.

In general, it might be a good idea to avoid class variables altogether.

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



Related Topics



Leave a reply



Submit