Reputation: 279
class Temp1
def add(s)
match = 'test'
self.class.class_eval do
define_method(s) do
puts match
end
end
#match ='haha'
end
end
As i thinks of it, 'match' is a local variable, so i don't understand how it can see it from another method, plus if uncomment #match ='haha', method will print 'haha' somehow. Can somebody explain it?
Also, i don't see difference here between using class_eval or instance_eval, seems like it do the same thing.
And, at last but not least, can I create class method here using define_method? So I can call it like Temp1.something instead of Temp1.new.something?
Upvotes: 2
Views: 1288
Reputation: 118271
Because blocks (do...end) are closures and have access to their surrounding scope.
You used block with class_eval
,so it has the access to its surroundings,which is the scope of the method add
. Now you use another block with define_method
,which as also has the access to the scope of the method add
,via the block with the class_eval
.match
local variable has been created inside the scope of the method add
. So the blocks has the access to the variable.
And, at last but not least, can I create class method here using define_method?
No you can't.define_method
Defines an instance method in the receiver.self.class
is Temp1
. Now under Temp1.class_eval do..end
,you are defining instance methods of the class Temp1
,with the method define_method
.define_method
is a private class method of all the classes,in which ancestor chain Object
class present.
class C;end
C.private_methods.grep(/define_/)
# => [:define_method]
Also, i don't see difference here between using class_eval or instance_eval, seems like it do the same thing.
Okay! Let me explain for you. You can't see the difference here,as Teamp1
is a Class
and also an instance of a Class
. In both call class_eval
and instance_eval
,self
is being set to Teamp1
,by their respective definition as documented.
class C
def self.bar;11;end
def baz;12;end
end
C.is_a? Class # => true
C.instance_of? Class # => true
C.class_eval{ bar } # => 11
C.instance_eval{ bar } # => 11
Hope this helps!
Upvotes: 6