class String
def hello
"world"
end
end
String.class_eval {
def world
"hello"
end
}
"a".world
=> "hello"
"b".hello
=> "world"
他们似乎做同样的事情 - 添加一个方法到现有的类。那有什么区别?猴子补丁vs class_eval?
class String
def hello
"world"
end
end
String.class_eval {
def world
"hello"
end
}
"a".world
=> "hello"
"b".hello
=> "world"
他们似乎做同样的事情 - 添加一个方法到现有的类。那有什么区别?猴子补丁vs class_eval?
随着class_eval
你可以做更多的事情动态:
>> met = "hello" #=> "hello"
>> String.class_eval "def #{met} ; 'hello' ; end" #=> nil
>> "foo".hello #=> "hello"
class_eval做概念类重新开放(或猴子修补)。大多数语法差异。如果您将字符串传递给class_eval
(如Michael的示例),则在字符串中的语法大多与class String; ... end
中的语法相同。如果你传递块:String.class_eval { ... }
它比较如下:
这将是有趣的,知道其他差异
其他答案都很好。想要添加class_eval
可以在需要引用类不是通过其常量或修补特定对象时使用。
例如
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
您可以使用class_eval
修补特定对象不affectin整根类。
obj = "asd"
obj.singleton_class.class_eval <<-eof
def asd
puts "gah"
end
undef_method :some_method
以上是一样的:
class << obj
...
end
instance_eval
将不得不使用一些稍有不同的行为。
我觉得这个问题和答案有趣: How to monkey patch a ruby class inside a method
也有大约instance_eval
VS class_eval
的问题,但我没有一个链接方便。