How to reference global variables and class variables?
我是编程新手。 现在我正在研究Ruby。 据我所知,全局变量是在全局命名空间中定义的(所以在任何类或函数之外)。 我正在读一些东西,它说全局变量在它们之前有一个
所以:
1 2 3 4 | edmund = 123 def my_function() 456 + $edmund end |
也是类变量(以
全球范围是涵盖整个计划的范围。全局变量享有全局变量,可通过其初始美元符号($)字符识别。它们随处可用,创建自己的全局变量可能很诱人,特别是初学程序员。但他们并不总是一个好主意。
1 2 3 4 5 6 7 8 9 | $gvar ="I'm a global!" class C def examine_global puts $gvar end end c = C.new c.examine_global # I'm a global! |
类变量以两个符号开头:例如@@ var。尽管它们的名称,类变量不是类作用域。相反,它们是类层次结构范围。最简单的说,类变量背后的想法是它提供了一个存储机制,该机制在类的类和实例之间共享,并且对任何其他对象都不可见。
1 2 3 4 5 6 7 8 9 10 11 | class Parent @@value = 100 end class Child < Parent @@value = 200 end class Parent puts @@value end |
打印的内容是200. Child类是Parent的子类,这意味着Parent和Child共享相同的类变量 - 不是具有相同名称的不同类变量,而是相同的实际变量。当您在Child中分配给@@值时,您将设置在整个层次结构中共享的唯一@@值变量 -
也就是说,由Parent和Child以及其中任何一个的任何其他后代类。
并给予应有的信誉 - 这个解释来自David A Black的"The Well Grounded Rubyist",这是了解Ruby的最佳资源之一。
好问题。不幸的是,你只是跳下了一个兔子洞,但是你必须最终落入红宝石才能开始理解真正错综复杂的洞穴。
关于第一个问题,关于
1 2 3 4 5 6 7 | def mk_foo() $foo ||="foo"; end $foo # => nil mk_foo # =>"foo" $foo # =>"foo" mk_foo.object_id # => 70299647799620 $foo.object_id # => 70299647799620 |
如您所见,当
1 2 3 4 5 6 7 | class CanSeeFoo def see_foo() $foo; end end CanSeeFoo.new.can_see_foo # =>"foo" CanSeeFoo.new.can_see_foo.object_id # => 70299647799620 |
至于类变量问题,这就是兔子洞开始的地方。首先,你是正确的,
类变量在定义类的所有子类(在继承树的所有子级别)都是静态的。这里的含义是,如果任何子类更改了类变量,它将在所有相关的子类中更改,直到定义的类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class A; end class B < A; @@foo ="foo"; end B.class_variable_get(:@@foo) # =>"foo" A.class_variable_get(:@@foo) # => raises NameError"uninitialized class variable @@foo in A" class C < B; end C.class_variable_get(:@@foo) # =>"foo" class D < C def self.change_foo(); @@foo ="bar"; end def change_foo(); @@foo ="baz"; end end D.class_variable_get(:@@foo) # =>"foo" class E < D; end E.class_variable_get(:@@foo) # =>"foo" D.change_foo # =>"bar" D.class_variable_get(:@@foo) # =>"bar" E.class_variable_get(:@@foo) # =>"bar" C.class_variable_get(:@@foo) # =>"bar" B.class_variable_get(:@@foo) # =>"bar" D.new.change_foo # =>"baz" D.class_variable_get(:@@foo) # =>"baz" E.class_variable_get(:@@foo) # =>"baz" C.class_variable_get(:@@foo) # =>"baz" B.class_variable_get(:@@foo) # =>"baz" A.class_variable_get(:@@foo) # => raises NameError"uninitialized class variable @@foo in A" |
至于访问类和实例变量,在没有使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class A @@foo ="foo" # the second argument `true` adds the writer method `#bar=` attr :bar, true def self.foo(); @@foo; end def self.foo=(v); @@foo = v; end def initialize() @bar ="bar" end end class B < A; end A.foo # =>"foo" B.foo ="foobar" A.foo # =>"foobar" B.foo # =>"foobar" a = A.new a.bar # =>"bar" a.bar ="baz" a.bar # =>"baz" a.foo # => raises NoMethodError: undefined method `foo' for #<A:0x ... |
您可以在ruby核心文档中看到属性访问器方法:http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-attr。此外,ActiveSupport(http://rubygems.org/gems/activesupport)具有用于定义类变量访问器的"
这是简单的事情。下一步是理解"单例类",也称为"特征类"或"元类"(维基百科:元类)(请记住,ruby中的所有内容都是Object,包括类和模块结构)。在这里,我将向您指出Yehuda Katz的一篇优秀文章:Ruby中的元编程:它是关于自我的全部,以及另一个Stack Overflow问题:类<< Ruby中的自我成语。
作为预览:单例类(不要与单例设计模式混淆)允许您访问特定类或模块的方法和实例数据。有关相关文档,请参阅核心文档:http://www.ruby-doc.org/core-1.9.3/Object.html#method-i-singleton_class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class A; end class B < A; class << self def foo() @foo end def foo=(v) @foo = v; end end end B.foo ="foo" class C < B; end A.foo # => raises NoMethodError: undefined method `foo' for A:Class B.foo # =>"foo" C.foo # => nil B.foo ="baz" B.foo # =>"baz" C.foo # => nil C.foo ="foo" C.foo # =>"foo" B.foo # =>"baz" |
最后,请记住使用Ruby-Core文档。对于理解上述内容最有用的是:
- http://www.ruby-doc.org/core-1.9.3/Object.html
- http://www.ruby-doc.org/core-1.9.3/Module.html
- http://www.ruby-doc.org/core-1.9.3/Class.html
美元符号是变量名称的一部分,因此必须如下声明:
1 | $edmund = 123 |
这与实例和类变量相同:它们的名称以
看看这些文章:
http://www.rubyist.net/~slagell/ruby/globalvars.html
和
你如何在Ruby中使用全局变量或常量值?