当我使用Class.new
时,由于某种原因,结果类的类变量相互干扰:
# ruby 2.1.6p336 (2015-04-13 revision 50298) [i686-linux]
result = Class.new do
p self # #<Class:0xb7cd5624>
@@foo = 1
def foo
p @@foo
end
end
result2 = Class.new do
p self # #<Class:0xb7cd54d0>
@@foo = 2
def foo
p @@foo
end
end
result.class_variable_set(:@@foo, 3)
result.new.foo # expected 3, output 3
result2.new.foo # expected 2, output 3
为什么呢?引擎盖下发生了什么?
此外还有相关的警告信息,但我无法理解它们的含义,也无法找到好的描述。
warning: class variable access from toplevel
到目前为止,我发现的最接近的线索是:
对类变量的访问被认为是顶级,因为class关键字没有定义一个类名来提供保存类变量的范围。
(c)http://japhr.blogspot.ru/2009/06/more-information-about-class-variables.html
由于您没有使用
class
关键字创建类,因此您的类变量设置在Object
上,而不是Test
(c)https://stackoverflow.com/a/10712458/1432640
有人可以详细说明为什么会发生这种情况以及为什么它与我使用class
关键字时的情况如此不同?
答案 0 :(得分:1)
让我们一起来看看:
result = Class.new do
p self # #<Class:0xb7cd5624>
@@foo = 1
def foo
p @@foo
end
end
此时,result
已创建为Class
的实例,Class
的类变量@@foo
设置为1。
result2 = Class.new do
p self # #<Class:0xb7cd54d0>
@@foo = 2
def foo
p @@foo
end
end
此时,result2
已创建为Class
的实例,Class
的类变量@@foo
设置为2.
result.class_variable_set(:@@foo, 3)
这会将名为Class
的班级@@foo
中的类变量设置为值3。
result.new.foo # expected 3, output 3
输出为3,因为@@foo
从上面的class_variable_set
设置为3。
result2.new.foo # expected 2, output 3
在此语句发生之前已经创建了 result2
,因此不会执行@@foo = 2
。 result2 = Class.new ...
上面的构造已经创建了实例。 result2.new
创建了一个Class
的新实例,它会为Class
,而不是上面为result2 = Class.new ...
创建的代码执行构造函数在你构建result2
)之后已经执行了。基础Class
构造函数不了解@@foo
,也不使用它或设置它。所以@@foo
的值仍为3。
关于警告信息:
警告:来自toplevel的类变量访问
您可能希望Google搜索警告消息,因为有几个很好的链接可供阅读。特别是,您可能希望查看The many gotchas of Ruby class variables。这篇简短的文章也解释了我上面所描述的内容。
<小时/> 如果要为新的动态创建的类创建单独的类变量,可以在创建类之后创建/设置类变量。您可以通过将类指定为常量来命名类:
1.9.2-p330 :017 > result.class_variable_set(:@@bar, 3)
=> 3
1.9.2-p330 :018 > result2.class_variable_set(:@@bar, 4)
=> 4
1.9.2-p330 :019 > R1 = result
=> R1
1.9.2-p330 :020 > R2 = result2
=> R2
1.9.2-p330 :021 > class R1
1.9.2-p330 :022?> def bar
1.9.2-p330 :023?> p @@bar
1.9.2-p330 :024?> end
1.9.2-p330 :025?> end
=> nil
1.9.2-p330 :026 > class R2
1.9.2-p330 :027?> def bar
1.9.2-p330 :028?> p @@bar
1.9.2-p330 :029?> end
1.9.2-p330 :030?> end
=> nil
1.9.2-p330 :031 > R1.new.bar
3
=> 3
1.9.2-p330 :032 > R2.new.bar
4
=> 4
1.9.2-p330 :033 >
答案 1 :(得分:0)
类变量在整个类层次结构中共享。您可能希望将class instance variables用于您的用例。
$('#delivery_option_22_6').on('change', function() {
if ($(this).is(':checked')) {
// Show popup window
alert("selected");
}
});
Ruby, class variables and inheritance ? super class @@var gets changed?
答案 2 :(得分:0)
Blocks创建一个新的嵌套词法范围并关闭其周围的词法范围。但是,它们不会改变动态范围。
动态范围在块内与其外部保持相同,即self
的值,默认定义的值,当前类。
顶级的类变量成为Object
的类变量。而且,这两个块共享相同的外部范围。因此,它们共享相同的类变量。
请注意,某些方法实际上执行更改了块的动态范围,例如: instance_exec
和instance_eval
更改self
的值。