Ruby:定义类变量时,类_exec产生意外结果
在Ruby中,当使用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
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