Whats the difference between class_eval and class << className?

我是研究僧i 提交于 2019-12-10 11:16:43

问题


I am a Ruby starter. I found both of these are quite similar (in output), but i couldn't understand the difference in the below context. For example, I have a class

class Say
  def self.hello
    puts "hello"
  end
end

and can be extended like this

class << Say
  def hi
    puts "hi"
  end
end

and also like this

Say.class_eval do
  def self.bye
    puts "bye"
  end
end

When should I use << and when class_eval?


回答1:


class_eval doesn't really have anything to do with class << className.

A.class_eval do
   ...
end

is equivalent to

class A
  ...
end

with a few differences. class_eval uses a block (or a string, but ignoring that for the moment) which means it closes over the containing lexical scope. In other words you can use local variables from the surrounding scope. The common class block introduces a brand new scope. Likewise you can create the block and pass it to many different class_eval's, and the body of the block will be executed in the context of the class you are calling class_eval on.

class << className opens the singleton class of className, allowing you to define class methods.

class << A
  def foo
    ...
  end
end

Is the same as

def A.foo
  ...
end

Note that they are oly class methods if A happens to be a class (almost) all objects in ruby have singleton classes and you can define methods for them using either of those two syntaxes. The advantage of class << obj is mainly if you're defining many singleton methods in one go.




回答2:


As already said class_eval has really not much to do with

class <<self

even if they seem to do the same thing in your example (while the effect is similar it does not do the same, there are subtle differences).

Here is another example where the usage of the second form is far more clearer:

class A

end


a = A.new
b = A.new

class <<b
  def say_hi
    puts "Hi !"
  end
end


b.say_hi # will print "Hi !"
a.say_hi # will raise an undefined method

a and b are both objects of the same class A but we added a method to the metaclass of b so the method say_hi is only available to the b object.



来源:https://stackoverflow.com/questions/5391541/whats-the-difference-between-class-eval-and-class-classname

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!