工作在一个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'来获得所提到的错误。 –