2
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?

1 Answer 1

6

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!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.