Ruby元编程:初始化singleton_class变量
- 为什么
Foo.val
在调用Foo.set
之前返回nil
而不是"foo"
? - 在课堂评估中是否有任何初始化
@val
机制? -
@val = "foo"
存放在哪个范围内?class Foo class << self @val = "foo" attr_reader :val def set(val) @val = val end end end p Foo.val # nil Foo.set("bar") p Foo.val # "bar"
您可以像这样在Foo中初始化@val
:
class Foo @val = "foo" class << self attr_reader :val def set(val) @val = val end end end p Foo.val #=> "foo" Foo.set("bar") p Foo.val #=> "bar"
你的代码不是在Foo上初始化@val
,而是在Foo的元类上初始化
Ruby通常在解析它们时执行表达式。 你的代码没有按预期执行的原因是因为你正在为Foo的单例类设置一个类实例变量,但另一方面你正在访问Foo本身的类实例变量,这就是为什么它不起作用:
class << self @val = "foo" # scope is class scope of singleton class of Foo attr_reader :val def set(val) # scope is instance scope of singleton class of Foo (equal to Foo itself) @val = val end end
这就是为什么Foo.val
在你的情况下产生nil
- 它尚未设置。
在class级评估中设置val
可以通过Victor已经certificate的方式来实现。
有关范围的讨论,另请参阅此post 。
无需使用#set。 只需定义#val方法并使用nil guard:
class Foo class << self def val; @val ||= "bar" end end end p Foo.val #=> "bar"