我正在尝试一些ruby元编程,并且与instance_eval()有些混淆。
见下面的例子
@instance_var = 'instance_var'
local_var = 'local_var'
obj = Object.new
obj.instance_eval { p @instance_var; p local_var }
obj.instance_eval { @instance_var = 'instance_var_in_obj'; local_var = 'local_var_in_obj' }
p @instance_var; p local_var
我希望@instance_var和local_var都能在块中传递/修改但我得到了
nil
"local_var"
"instance_var"
"local_var_in_obj"
因此我们可以在instance_val
中共享(传递/修改)本地变量,但实例变量属于self
无法共享。
和约instance_exec
:
obj.instance_exec(@instance_var) {|instance_var| p instance_var; instance_var = @instance_var }
=> "instance_var"
@instance_var
=> "instance_var"
现在我可以传递我的外部实例var,但仍然无法修改它。
@instance_arr = []
obj.instance_exec(@instance_arr) {|instance_arr| instance_arr << 'in_block' }
@instance_arr
=> ["in_block"]
obj.instance_exec(@instance_arr) {|instance_arr| instance_arr = [] }
@instance_arr
=> ["in_block"]
使用数组的实例var我可以修改我的实例var但仅限于当前数组对象
摘要播放instance_eval
或instance_exec
本地变量而不是实例变量?
我错过了一些概念吗?
答案 0 :(得分:1)
经过我的朋友的一些搜索和建议,我想我发现了问题。
在ruby中,当您的代码运行Context
和self
时,当您使用binding
或local vars
而没有设置method
时,有两个self.xxx
将检查它是否在binding
对象中作为local var
如果不是,Ruby会认为它是一种方法,然后搜索您的self
对象以查找其定义并调用它。
想一想:
class A
def test
4
end
def use_variable
test = 5
test
end
def use_method
test = 5
self.test
end
end
a = A.new
a.use_variable # returns 5
a.use_method # returns 4
已解释WHY
的{{1}}因为其文档instance_eval
刚刚在给定的块中更改了instance_eval
而未触及self
因此将搜索方法新的binding
,本地值仍然在同一个self
对象中。
关于binding
我对此并不十分肯定,但似乎是实例变量(在vars前缀),它将在instance_exec
上搜索直接跳过self
,因此binding
您的instance_exec
属于旧版@instance_arr
,self
阻止您将其作为新instance_exec
块中的local var
块(块具有自己的范围)但它的值实际上是binding
的引用,因此在新的@instance_arr
上调用方法,例如local var
,它将改变它们两者,因为它们共享相同{{1}但是,当您为新的push
分配新的Array instance
时,他们不再引用与Array instance
相同的local var
。
答案 1 :(得分:0)
为了评估局部变量,你需要传入字符串`&#34; local_var&#34;它将返回局部变量的值。根据我对the documentation的解释,如果传入一个块,则无法传入参数。
块形式中实例eval的行为是作为闭包访问该调用所在对象的实例变量和私有方法。
带参数的实例eval的行为允许您评估该调用范围内的字符串。