Ruby:定义类变量时,类_exec产生意外结果

Ruby:定义类变量时,类_exec产生意外结果,ruby,Ruby,在Ruby中,当使用class\u exec定义类的内容时,我得到了意想不到的结果。当我在发送到class\u exec的块中定义类变量时,类变量是在对象上定义的,而不是在调用class\u exec的类上定义的: class X; end X.class_exec do @@inner_value = "123" def inner_value @@inner_value end def inner_value=(arg) @@inner_value = arg

在Ruby中,当使用
class\u exec
定义类的内容时,我得到了意想不到的结果。当我在发送到
class\u exec
的块中定义类变量时,类变量是在
对象上定义的,而不是在调用
class\u exec
的类上定义的:

class X; end
X.class_exec do
  @@inner_value = "123"
  def inner_value
    @@inner_value
  end
  def inner_value=(arg)
    @@inner_value = arg
  end
end

obj1 = X.new
puts obj1.inner_value
puts @@inner_value
puts Object.class_variables
产生:

123
123
@@inner_value
123
使用
class\u eval
时不会发生这种情况:

X.class_eval(<<-RUBY)
  @@inner_value = "123"
  def inner_value
    @@inner_value
  end
  def inner_value=(arg)
    @@inner_value = arg
  end
RUBY

obj1 = X.new
puts obj1.inner_value
puts @@inner_value
puts Object.class_variables
还有一个错误:

uninitialized class variable @@inner_value in Object (NameError)
class_eval的结果是我期望在这两种情况下都会发生的结果。我在MRI 1.8.7和MRI 1.9.3上都试过了,在Windows XP上运行时得到了相同的结果


这是预期的行为吗?若然,原因为何?如果没有,bug?

类变量将绑定到编译时声明它们的类。传递给
class\u exec
的块在传递给
class\u exec
之前经过编译,因此类变量绑定到
对象

我猜你的类_exec在顶层,在Object中,所以这就是它们要去的地方。证明:

public

class Object
    @@x = "ribbit"
end

def foo
    puts "test: #{@@x}"
end

x = Object.new
x.foo
这就是为什么在模块中使用类变量时,包含该模块的所有类(通过包含的方法)将看到相同的类变量。类变量绑定到模块。如果运行此命令:

class WithClassVars
    def self.classvars
        @classvars ||= {}
    end

    def classvars
        self.class.classvars
    end
end

class A < WithClassVars;end
class B < WithClassVars;end

a = A.new
b = B.new
a.classvars[:a] = 1
b.classvars[:a] = 2

puts a.classvars
puts b.classvars
class WithClassVars
    def self.classvars
        @classvars ||= {}
    end

    def classvars
        self.class.classvars
    end
end

class A < WithClassVars;end
class B < WithClassVars;end

a = A.new
b = B.new
a.classvars[:a] = 1
b.classvars[:a] = 2

puts a.classvars
puts b.classvars