关于oop:Ruby动态类。 如何修复“警告:来自toplevel的类变量访问”

Ruby Dynamic Classes. How to fix “warning: class variable access from toplevel”

我正在尝试编写一个程序,根据从文件中读取的配置动态定义ruby类。 我知道我可以使用Class.new来做到这一点。 这是一个示例程序:

1
2
3
4
5
6
7
8
9
10
11
x = [1,2,3]

Test = Class.new do
  @@mylist = x

  def foo
    puts @@mylist
  end
end

Test.new.foo

当我运行它时,我得到以下输出(与ruby 1.9.3p0一起运行):

1
2
3
4
5
c:/utils/test.rb:4: warning: class variable access from toplevel
c:/utils/test.rb:7: warning: class variable access from toplevel
1
2
3

有谁知道是什么导致这些警告以及我如何摆脱它们?

我已经尝试更换线路了

1
@@mylist = x

有了这个

1
class_variable_set(:@@mylist, x)

但是当我这样做时,我得到了这个错误:

1
2
3
c:/utils/test.rb:7: warning: class variable access from toplevel
c:/utils/test.rb:7:in `foo': uninitialized class variable @@mylist in Object (NameError)
        from c:/utils/test.rb:11:in `
'

提前致谢!


这不是你认为它正在做的事情。 由于您没有使用class关键字创建类,因此您的类变量在Object上设置,而不是Test。 这种影响非常大,这就是Ruby警告你的原因。 类变量在祖先之间共享,对象通常从Object继承。


要删除此警告,您应该使用class_variable_set方法:

1
2
3
4
5
6
7
8
9
x = [1,2,3]

Test = Class.new do
  class_variable_set(:@@mylist, x)

  def foo
    puts @@mylist
  end
end


如果你只想抑制这个警告,你可以使用

1
$VERBOSE = nil

在你的代码顶部


在声明类时,您可以在类上声明类级变量,而不是在类上定义类"mylist"类变量,如下所示。 显示了两种不同的方法。 前者仅适用于1.9,后者适用于两种版本,但不太惯用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
x = [1,2,3]

Test = Class.new do
  def foo
    puts @@mylist
  end
end

# ruby 1.9.2
Test.class_variable_set(:@@mylist, x)  

# ruby 1.8.7
Test.class_eval {
  @@mylist = x
}

Test.new.foo