工作在一個Ruby程序我正在尋找將一些狀態數據從實例變量移動到類變量,它讓我明白,雖然實例變量是自動生動的(如果你嘗試閱讀「沒有初始化」它們,它們是自動的初始化爲nil
),類變量不是 - 這對我來說看起來非常不一致(與大多數Ruby語法非常一致)。Ruby類變量不會自動生成?
樣例程序:
class Test
def id
@id.to_i
end
def id=(i)
@id = i
end
def nextid
self.id = id + 1
end
end
t = Test.new
puts t.nextid #=> 1
puts t.nextid #=> 2
在這種情況下,調用Test::id
時,如果@id
沒有初始化,紅寶石將它自動vivify到nil
(之後我to_i
它獲得0)。
現在我決定,我要跨Test
實例共享的運行ID,所以我把它改寫這樣的:
class Test
def id
@@id.to_i
end
def id=(i)
@@id = i
end
def nextid
self.id = id + 1
end
end
t = Test.new
puts t.nextid
puts t.nextid
應該工作一樣,我想,但沒有:
NameError: uninitialized class variable @@id in Test
但這種變通辦法(!?):
class Test
def id
(@@id ||= 0).to_i
end
def id=(i)
@@id = i
end
def nextid
self.id = id + 1
end
end
t = Test.new
puts t.nextid #=> 1
puts t.nextid #=> 2
(當然,這樣做延遲初始化爲0後我可以放棄to_i
,但我保持一致)。
它看起來像Ruby的理解「惰性初始化」,將其視爲需要不丟NameError
魔術 - 儘管||=
是假想只是語法糖x = x || val
(其中順便說一句不適合INITING類變量的工作,感謝要求)。
怎麼回事?
'X || = val'是有點兒相當於'X || x = val',而不是'x = x || val'。另外,在你的代碼中,你爲什麼需要一個實例方法來設置一個類變量? –
你測試了哪個ruby版本?我已經嘗試了ruby-2.2中的第二個例子。2,我得到了'NoMethodError:undefined method'+'for nil:NilClass'而不是'NameError:未初始化的類變量@@ id' – fangxing
@fangxing:我不認爲這取決於Ruby版本。我會說這是一個錯誤的問題。你可以使用'self.id = id + 1'來獲得所提到的錯誤。 –