Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between instance_eval and class << self?

Tags:

ruby

I can't seem to grasp the exact difference between these two "constructs". To my mind, the following small script should output the same thing three times:

class Example
  puts self

  class << self
    puts self
  end

  instance_eval do
    puts self
  end
end

However, the output is:

Example
#<Class:Example>
Example

Here's my rationale:

  • Example is an instance of Class, so self in the class body refers to that;
  • 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);
  • instance_eval runs the block in the given instance, so, in my case it's pretty much the same as putting the code in the block directly in the class body.

My current guess is that class << self inserts a ghost class between Example and Class and sets self to that, but the output of #<Class:Example> is not confirming that at all.

So what is wrong with my rationale?

like image 640
Felix Avatar asked Jan 20 '23 21:01

Felix


1 Answers

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.

like image 145
Jörg W Mittag Avatar answered Jan 29 '23 04:01

Jörg W Mittag