mhaseeb
mhaseeb

Reputation: 1779

Instance created before method definition

Why does a created before class_eval in the code have access to world?

class Hello; end

a = Hello.new

Hello.class_eval {def world; puts "Hi" end}

b = Hello.new

a.world #=> "Hi"
b.world #=> "Hi"

How does class_eval work behind the scenes?

Upvotes: 0

Views: 44

Answers (2)

Jörg W Mittag
Jörg W Mittag

Reputation: 369624

Why does a created before class_eval in the code have access to world?

It doesn't. Methods are stored in modules, not the instances. (Well, modules are instances of Module, but that's irrelevant here.) All a knows is that it's an instance of Hello, i.e. its class pointer points to Hello (again, technically that's not true, its class pointer points to its singleton class and its singleton class's superclass pointer points to Hello, but that is also irrelevant here). When a gets sent the world message it checks its class, Hello, for a world method, and sure enough, there is one because it was added before the message was sent, so it executes it.

How does class_eval work behind the scenes?

This has nothing to do with class_eval, it would work exactly the same way without metaprogramming. class_eval is a red herring here:

class Hello; end

a = Hello.new

class Hello; def world; puts "Hi" end end

b = Hello.new

a.world # "Hi"
b.world # "Hi"

Upvotes: 0

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121020

Classes in ruby are open. As Hello was given with a new method, method dispatch on all instances got updated with this. If you want to extend a only, call class_eval on a’s eigenclass:

class Hello; end

a = Hello.new

class << a; def world; puts "Hi" end end
# or, the equivalent: 
# a.singleton_class.class_eval { def world; puts "Hi" end }

b = Hello.new

a.world #⇒ "Hi"
b.world #⇒ NoMethodError: undefined method `world' for #<Hello>

Upvotes: 6

Related Questions