Ruby 元编程:初始化 singleton_class 变量

发布于 2024-11-28 09:27:40 字数 377 浏览 3 评论 0原文

  • 为什么在调用 Foo.set 之前,Foo.val 返回 nil 而不是 "foo"
  • 是否有任何机制可以在类评估时初始化 @val
  • @val = "foo" 存储在哪个范围内?

    类 Foo
      类<<自己
        @val =“富”
        attr_reader :val
    
        def 设置(值)
          @val = val
        结尾
      结尾
    结尾
    
    p Foo.val # nil
    Foo.set("酒吧")
    p Foo.val #“酒吧”
    
  • Why does Foo.val return nil instead of "foo" before calling Foo.set?
  • Is there any mechanism for initializing @val on class evaluation?
  • In which scope is @val = "foo" stored into?

    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"
    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

再可℃爱ぅ一点好了 2024-12-05 09:27:40

您可以像这样在 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 的元类上初始化

You can initialize @val in Foo like this:

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"

Your code initializes @val not on Foo, but on Foo's metaclass

樱娆 2024-12-05 09:27:40

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 - 它尚未设置。

在类评估上设置 val 可以通过 Victor 已经演示的方式来实现。

另请参阅这篇文章有关范围的讨论。

Ruby generally executes expressions upon parsing them. The reason why your code did not perform as expected is because you are setting a class instance variable for the singleton class of Foo, but on the other hand you are accessing the class instance variable of Foo itself, that's why it doesn't work:

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

That's why Foo.val yields nil in your case - it hasn't been set yet.

Setting val on class evaluation can be achieved in the way that Victor already demonstrated.

See also this post for a discussion about scope.

新雨望断虹 2024-12-05 09:27:40

无需使用#set。
只需定义 #val 方法并使用 nil 保护:

class Foo
    class << self
        def val; @val ||= "bar" end
    end
end
p Foo.val  #=> "bar"

No need to use #set.
Simply define #val method and use nil guard:

class Foo
    class << self
        def val; @val ||= "bar" end
    end
end
p Foo.val  #=> "bar"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文