2009-01-29 20 views
1

在紅寶石我想做的事情大致有以下幾種,並把它打印出「改變」:ruby​​:如何在另一個對象內引用@foo?

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?」。

我不想要像「使用全局變量」或「使用類變量」或「通過@foochange_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) 

回答

1

遲到了,但你可以通過當前上下文方法,然後EVAL在這種特定情況下的實例變量的操作:

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 
1

我知道這是你不想要的答案,但是從你的描述中,你應該真的應該使用一個類變量。另外,找到變量的「所有者」是不可能的,因爲所有具有特定內容(例如「原始」)的字符串都是無法區分的 - 沒有記錄它來自何處(除非@foo實際上是一種定製對象,您可以在其中存儲對父級的引用)。

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" 
+0

原因很簡單:別人使用jruby創建了一個DSL,無論出於何種原因,他們選擇將各種命令的中間結果存儲在名爲@response的變量中。由於這個變量在jruby和java中都被用於整個dsl,所以我堅持使用它。 – 2009-01-29 03:16:19

0

我覺得有點傻這樣做,但我會把它反正。看起來像桑博有正確的想法。我不知道那個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" 
相關問題