Reputation: 1779
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
Reputation: 369624
Why does
a
created beforeclass_eval
in the code have access toworld
?
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
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