2012-03-24 100 views
1

也許我只是對結構不夠了解而盲目地使用它們,但下面的結果對我來說似乎不合理。爲什麼這個變量消失在一個結構中?

class VarTest < Struct.new(:email) 
    def perform 
    puts "Start: #{email}" 
    if email == "nothing" 
     email = "bad email" 
    end 
    puts "End: #{email}" 
    end 
end 
VarTest.new("[email protected]").perform 

意外的輸出:

Start: [email protected] 
End: 

如果我的代碼更改爲:

class VarTest < Struct.new(:email) 
    def perform 
    e = email 
    puts "Start: #{e}" 
    if e == "nothing" 
     e = "bad email" 
    end 
    puts "End: #{e}" 
    end 
end 

VarTest.new("[email protected]").perform 

我們得到預期的輸出:

Start: [email protected] 
End: [email protected] 

有人能解釋一下這是怎麼回事?

謝謝。

+0

實際的目標是什麼?換句話說,爲什麼你使用繼承而不是僅僅是'VarTest = Struct.new(:email)'然後'VarTest.new('[email protected]')'? – 2012-03-24 23:28:07

+0

它被延遲工作用作入隊的一部分。無論如何,爲什麼以這種方式使用它會導致這種行爲? – chrishomer 2012-03-24 23:30:06

回答

4

如果您將email = "bad email"替換爲self.email = "bad email"它將按預期工作。使用setter時總是如此。

原因很簡單:當Ruby遇到裸詞時,它會嘗試將其解析爲本地變量。如果沒有,它會嘗試按該名稱調用方法。在課堂內部,自我是隱含的接受者,所以讀者只是在工作。現在對於作者來說存在一個問題。如果你寫了foo = "bar"之類的東西,Ruby會創建一個新的局部變量,因此你需要明確地指定接收者。

這種情況有點棘手:if email == "nothing"使用getter。但是,解析器仍然會看到email = "bad email",並且本地變量email將設置爲nil。當解析器將一個裸詞看作是一個賦值的LHS時,這總是會發生。這個本地nil值是什麼使它看起來像email消失的值(您可以通過僅將最後的puts更改爲puts "End: #{self.email}"來驗證)。

+0

真棒。所以這不是Structs所特有的。我沒有意識到這是結構變量的工作原理。事後看來是完美的。那麼,學習會繼續,這就是讓這些東西變得有趣的原因!謝謝! – chrishomer 2012-03-25 00:05:16

相關問題