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"