变量持有目标对象的引用,和我们所熟悉的 C# / Java 不同的是,Ruby 变量并没有内在类型。作为一种动态解析执行的语言,其变量类型只在其执行期决定,我们也因此能改变变量所持有对象的类型,显然在 C# / Java 里是不允许的 (Object 类型变量和这个不是一回事,如果不明白,建议再看看面向对象理论)。
a = 1 puts a.class #Fixnum a = "s" puts a.class #String
或许你看过 C# 3.0,但需要明白这和那个隐式类型变量(Implicitly typed local variables)并不是一回事。"var" 关键字只是一种简写,一种语法糖,编译器会自动推断,并在编译时决定其类型。细节可以参考我前面写的文章。
名字
这里提到的命名规则,仅仅是变量,有关类型、方法的命名参考后面的章节。
(1) 名字由一个大小写字母(a-z)或下划线(_)开头,后跟任意个命名字符(大小写字母、下划线或数字)组成。
(2) 局部变量通常由小写字母开头。
(3) 实例变量名以"@"开始,第一个命名字符小写。
(4) 类变量以 "@@" 开始,第一个命名字符大写。
(5) 全局变量以 "$" 开始。
(6) 常量名通常以大写字母和下划线组成。
关于 Ruby 命名前缀,感觉有点别扭。不过记忆的方法也很简单,根据其作用域,范围越大越有 "钱",自然全局变量是货真价实的 "$",然后是大家(对象实例)共有的"领导"——类变量,每月发两包子(@@);实例变量相比起来,只能是"白领"了,只有一个包子(@);最惨的就是局部变量了,什么都没有…… ~~~~~
$Global = "Word!" class Class1 @@I = 0 def initialize() @name = "Tom!" end def test() a = 123456 puts a end end
常量
Ruby 允许你改变常量值,这对我而言恐怕不是啥好事情。
NAME = "name" puts NAME # Line 100, 许木木说: 做好多好多有意义的事情。 # Line ... # Line 1000, 许木木说: 做好多好多有意义的事情。 NAME = "sss" # 我以为是重新定义了一个常量,其实不小心改了上面 "大哥" 的内容。 puts NAME
输出:
name
sss
main.rb:6: warning: already initialized constant NAME
输出结果里面的这个警告信息对于程序执行而言,并无任何约束作用。
作用域
在类或模块内的任意位置都可以访问此类或模块中定义的常量,在这之外,可以通过域作用符(::)访问。
示例1
NAME = "Tom" class Class1 def test() puts NAME end end puts NAME Class1.new().test()
示例2
class Class1 NAME = "Tom" def test() puts NAME end end puts Class1::NAME Class1.new().test()
全局变量贯穿整个程序,当我们 load 或 require 一个模块时,也会将其全局变量引入。因此,我们应该避免滥用全局变量,这可能和其他模块造成冲突。就个人感觉而言,我不太喜欢全局变量/常量这种东西,它更多地象很久以前结构化编程的遗迹。
test.rb
$name = "zhangsan" def test() puts $name end
main.rb
require "test.rb" $name = "lisi" # 原本以为创建了个新的家伙,却不小心 "改变" 了 "别人" 的 "财产"。 test()
类变量和 C# 类静态字段基本是一个东西,被所有实例对象共享。而实例变量仅属于当前实例,缺省情况下,在对象外部我们并不能访问它。