monkey patching vs class_eval?

社会主义新天地 提交于 2019-12-30 03:59:06

问题


class String
  def hello
    "world"
  end
end

String.class_eval {
  def world
    "hello"
  end
}

"a".world
=> "hello"
"b".hello
=> "world"

They seems to do the same thing -- adding a method to a existing class. So what's the difference?


回答1:


With class_eval you can do more dynamic things:

>> met = "hello" #=> "hello"
>> String.class_eval "def #{met} ; 'hello' ; end" #=> nil
>> "foo".hello #=> "hello"



回答2:


class_eval do conceptually class reopening (or monkey patching). There are mostly syntactic differences. If you pass string to class_eval (as in Michael's example) you have mostly the same syntax inside the string as in class String; ... end. If you pass block: String.class_eval { ... } it compares as follows:

  • inside class_eval block outer local variables are visible
  • inside reopened class outer local variables are NOT visible
  • inside class_eval you CANNOT assign constants and class variables scoped to the class
  • inside reopened class you CAN

It would be interesting to know the other differences




回答3:


Other answers are good. Want to add that class_eval can be used when you want reference class not by its constant or to patch particular object.

e.g.

huh = String
class huh
end
SyntaxError: (eval):2: class/module name must be CONSTANT

huh.class_eval <<-eof
def mamma
puts :papa
end
eof

"asdff".mamma
=> papa

You can use class_eval to patch particular object without affectin whole root class.

obj = "asd"
obj.singleton_class.class_eval <<-eof
def asd
puts "gah"
end
undef_method :some_method

The above is same as:

class << obj
  ...
end

instance_eval will have slightly different behavior by some usage.

I find this question and answers interesting: How to monkey patch a ruby class inside a method

Also there were questions about instance_eval vs class_eval but I don't have a link handy.



来源:https://stackoverflow.com/questions/9399358/monkey-patching-vs-class-eval

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