全局变量以$开头,它是全局可见的。Ruby内建的全局变量如$:和$LOAD_PATH表示require读取文件时寻找的目录数组。
类变量以@@开头,可被定义它的类以及其子类访问,也可被定义它的类和子类的实例访问。
class Example
@@cls_var = "defined in Example"
def self.cls_var
@@cls_var
end
def inst_var
@@cls_var
end
end
puts Example.cls_var # => "defined in Example"
puts Example.new.inst_var # => "defined in Example"
class SubExample < Example
@@cls_var = "modified in SubExample"
end
puts SubExample.cls_var # => "modified in SubExample"
puts SubExample.new.inst_var # => "modified in SubExample"class variable并不真正属于类,而是属于类体系结构。
@@cls_var = 1
class Example
@@cls_var = 2
end
puts @@cls_var # => 2因为@@cls_var被定义在Object类上,而Example继承自Object,所以Example也共享了这个类变量。
class Example
@@foo = ""
def foo
@@foo
end
end
class SubExample < Example
@@foo = "hello"
end
puts Example.new.foo # => "helloExample.new并不属于SubExample,竟然也被SubExample的修改所影响!
正因为很多地方都可以改变类变量,很难追踪是什么地方做了改变,所以不推荐使用它。
在类对象上定义的变量是实例变量以@开头,实例变量因为存在于在对象上,所以整个对象的类的继承链都可以使用。这与Java等静态语言不一样。
父类里定义的实例变量,子类方法可以使用:
class Example
def def_inst_var
@inst_var = "I am defined in Example"
end
end
class SubExample < Example
def inst_var
@inst_var
end
end
sub = SubExample.new
sub.def_inst_var
puts sub.inst_var # => "I am defined in Example"子类里定义的变量,父类方法也可以使用:
class Example
def inst_var
@inst_var
end
end
class SubExample < Example
def def_inst_var
@inst_var = "I am defined by SubExample"
end
end
sub = SubExample.new
sub.def_inst_var
puts sub.inst_var # => "I am defined by SubExample"类本身也是一种对象,它是Class类的实例,在类上定义的变量,叫类实例变量。类实例变量只能被类方法访问。
class Example
@cls_inst_var = "class instance variable"
def self.cls_inst_var
@cls_inst_var
end
end
puts Example.cls_inst_var # => "class instance variable"类实例变量因为存放在类对象上,所以可以被继承链上的类方法访问到。比如子类定义的类实例变量,父类的类方法能访问:
class Example
def self.cls_inst_var
@cls_inst_var
end
end
class SubExample < Example
@cls_inst_var = "class instance variable"
end
puts SubExample.cls_inst_var # => "class instance variable局部变量只属于当前的作用域,作用域的改变只取决于三个关键字:class, module和def。跟Java等语言不同,for,if,while等关键字并不会改变作用域。
def test(ok)
if ok
a = "I am OK!"
end
puts a
end
test(false) # => ""
test(true) # => "I am OK!"
比如子类定义的类实例变量,父类的类方法能访问:
例子错了,父类不行