【问题标题】:class_eval and context of class variables?class_eval 和类变量的上下文?
【发布时间】:2014-08-23 18:34:47
【问题描述】:

寻找解释为什么在Module.class_eval 块中的以下示例中,类变量查找不起作用:

class MyClass
  @@myvar = 123
  def self.myvar_getter
    @@myvar
  end
end

class MyClass
  p "#{self}, #{self.object_id}, #{singleton_class.object_id}"
  # output: "MyClass, 21055520, 21055500"
  p myvar_getter  # class method lookup working
  # output: 123
  p @@myvar       # class variable lookup working
  # output: 123
end

MyClass.class_eval do
  p "#{self}, #{self.object_id}, #{singleton_class.object_id}"
  # output: "MyClass, 21055520, 21055500"
  p myvar_getter  # class method lookup working as expected
  # output: 123
  p @@myvar       # class variable lookup NOT working (why ?)
  # output: -- following exception --
  #   a.rb:47: warning: class variable access from toplevel
  #   a.rb:47:in `block in <main>': uninitialized class variable
  #   @@myvar in Object (NameError)
end

您可能会看到范围似乎相同,self 是相同的,在这两种情况下都找到了类方法 :myvar_getter,但是在 @987654329 内的 Object 类中意外查找了类变量 @@myvar @ 堵塞。 除了因为之外,任何人都可以解释这种行为吗?

【问题讨论】:

  • 我认为这里的教训是类变量几乎永远不会按照您希望的方式运行。如果您对使用它们下定决心,则可以通过在相关类上明确使用 class_variable_get/set 来找到更一致的结果。
  • @IronSavior 感谢您的评论。我知道class_variable_get/set 方法。我什至读过 Yehuda Katz 关于metaprogramming in Ruby 的精彩文章,其中描述了范围、方法解析和方法定义之间的细微差别。但是没有什么可以解释这个问题的问题。是否还有另一个概念可以区分变量查找?
  • 我隐约记得在某些情况下类变量的行为在 ruby​​ 1.8 和 1.9 之间也不一致。它们可能有用例,但人们通常应该更喜欢在类的上下文中使用实例变量。 (为了以后遇到这个的人的利益)

标签: ruby inheritance metaclass


【解决方案1】:

我不得不经历一些虚弱的时刻,因为答案非常清楚和明显。

来自Module.class_eval 文档:

在 mod 的上下文中计算字符串或块,除了当一个 给定块,常量/类变量查找不受影响。这可以是 用于向类添加方法。 module_eval 返回评估结果 它的论点。

因此,如果我需要直接从 eval 块访问类变量(即不使用类变量 getter/setter 方法),我只需将代码作为字符串传递:

MyClass.class_eval <<-EOS
  p @@myvar       # class variable lookup is working from a string
  # output: 123  voila!
  EOS

【讨论】:

    猜你喜欢
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 2016-08-15
    相关资源
    最近更新 更多