在ruby中我想大致做以下几点并打印出“已更改”:
class Whatever
def change_foo
@foo="changed"
end
end
@foo = "original"
o = Whatever.new
o.change_foo
puts "it changed" if @foo == "changed"
puts "it did not change" if @foo == "original"
当然,问题在Whatever
内,@foo
属于Whatever
的实例。
有没有办法让change_foo
改变“全球”foo?问这个的另一种方式可能是“我可以引用哪个对象”拥有“@foo
?”。
我不希望像“使用全局变量”或“使用类变量”或“将@foo
传递给change_foo
”之类的解决方案。我特别询问上面的情况,我无法控制原始变量,也无法控制change_foo
的调用方式。
我已经提出了一个解决方法,我在构建时传递对全局对象的引用,但我并不是因为它需要我在适当的范围内实例化而无法实现它。
class Whatever
def initialize(main)
@main = main
end
def change_foo
@main.instance_variable_set("@foo","changed")
end
end
o = Whatever.new(self)
答案 0 :(得分:1)
我知道这是你不想要的答案,但是根据你的描述,你应该真的应该使用一个类变量。此外,找不到变量的“所有者”是不可能的,因为具有特定内容的所有字符串(例如,“原始”)都是无法区分的 - 没有记录它来自哪里(当然,除非@foo真的是一个自定义您可以存储对父项的引用的对象。)
答案 1 :(得分:1)
派对晚了,但您可以将当前上下文传递给该方法,然后在该特定上下文中对该实例变量的操作进行评估:
class Whatever
def changeFoo(context)
eval %q( @foo="changed" ), context
end
end
@foo = "original"
o = Whatever.new()
o.changeFoo(binding)
puts "it changed" if @foo == "changed"
puts "it did not change" if @foo == "original"
# => it changed
答案 2 :(得分:0)
为什么你想要做这样的事情超出我的范围......你不应该在你的根对象上定义实例变量,并且不惜一切代价避免全局变量。
这说明了实现这一目标的一些方法。您可以通过在脚本顶部定义$ self = self来避免使用对象空间。
无论如何,这里有一些工作示例代码,帮自己一个忙,不要使用它
class Whatever
def changeFoo
@foo="changed"
end
def changeFoo2(o)
o.instance_variable_set('@foo', 'changed')
end
def changeFoo3
ObjectSpace.each_object do |o|
if o.instance_of? Object and o.instance_variables.include?("@foo")
o.instance_variable_set('@foo', 'changed')
end
end
end
end
@foo = "original"
o = Whatever.new()
o.changeFoo()
puts "it changed" if @foo == "changed"
puts "it did not change" if @foo == "original"
o.changeFoo2(self)
puts "it changed" if @foo == "changed"
puts "it did not change" if @foo == "original"
@foo = "original"
o.changeFoo3()
puts "it changed" if @foo == "changed"
puts "it did not change" if @foo == "original"
答案 3 :(得分:0)
我觉得这样做有点傻,但无论如何我都会把它搞砸。看起来像sambo有正确的想法。我不知道那个ObjectSpace模块。甜。
我将它包装在一个模块中。
module What
@foo = 'bar'
class Whatever
def change_foo
What.instance_variable_set(:@foo, "changed")
end
end
end
w = What::Whatever.new
p What.instance_variable_get(:@foo)
# >> "bar"
w.change_foo
p What.instance_variable_get(:@foo)
# >> "changed"