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
的問題,但我沒有一個鏈接方便。