a = %w( ant bee cat dog elk ) # create an array a.each { |animal| puts animal } # iterate over the contents
5.times { print "*" } 3.upto(6) {|i| print i } ('a'..'e').each {|char| print char } |
::
双冒号
域作用符,将模块(类)与它的常量隔开
类重复定义,只是增加方法
在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字,创建一个 Symbol 对象的方法是在名字或者字符串前面加上冒号:
在 Ruby 中每一个对象都有唯一的对象标识符(Object Identifier),可以通过 object_id 方法来得到一个对象的标识符。例子如下:
前三行语句中的 :foo (或者 :"foo")都是同一个 Symbol 对象,其 object id 为327458,而后三行中的字符串”foo”都是不同的对象,其 object id 依次为24303850、24300010、24296170。
可见,每个 String 对象都是不同的,即便他们包含了相同的字符串内容;而对于 Symbol 对象,一个名字(字符串内容)唯一确定一个 Symbol 对象(Symbol 对象的字符串中不能含有’\0’字符)。
除了可以采用一般的字符串,还可以使用操作符(例如+, -, *, /),变量,常量,方法甚至类的名字来创建 Symbol 对象,例如:+就是一个合法的 Symbol 。实际上,在 Ruby 内部操作符、变量等名字本身就是作为 Symbol 处理的,例如当你定义一个实例变量时, Ruby 会自动创建一个 Symbol 对象,例如 @test 对应为 :@test 。
Symbol 和 String
Symbol 对象和 String 对象是完全不同的东西,对象标识符很明确的说明了这一点。
Symbol 转化为 String
使用 to_s 或 id2name 方法将 Symbol 转化为一个 String 对象:
1
2
3
4
5
6
|
irb(main):
001
:
0
>
:test
.id2name
=>
"test"
irb(main):
002
:
0
>
:test
.to_s
=>
"test"
irb(main):
003
:
0
> :
"I am a boy"
.to_s
=>
"I am a boy"
|
注意,每个 String 对象都是唯一的,因此对一个 Symbol 调用多次将产生多个 String 对象。
String 转化为 Symbol
除了在字符串前面加冒号,还可以使用 to_sym 或 intern 方法将 String 转化为 Symbol ,如果该 Symbol 已经存在,则直接返回。
使用 Symbol
正如前边提到的, Ruby 内部一直在使用 Symbol ,比如 Ruby 程序中的各种名字,Symbol本质上是 Ruby 符号表中的东西。使用 Symbol 处理名字可以降低 Ruby 内存消耗,提高执行速度,这点我们在下一篇文章中会看到。
那么 Symbol 对我们有什么用呢?当然也是内存。使用 String 的开销太大了,因为每一个String 都是一个对象。想想前边的例子,一个字符串每出现一次 Ruby 就会创建一个 String 对象。
通常来讲,当你面临 String 还是 Symbol 的选择时,可以参考以下标准:
那么什么时候我们会用到名字呢?很多时候都会,比如枚举值、关键字(哈希表关键字、方法的参数)等等
作为哈希表的 key
哈希表是 Symbol 应用最为广泛的地方。在ruby中,哈希和数组类似,一个哈希表是一系列 key/value 对的集合,只不过它的 key 取值范围更广泛,可以是任何对象,比如正则表达式。
但通常我们都会取有意义的 key ,比如 String、Symbol 。
下面这个哈希表表示按城市分类的一些机器的集合:
如果要引用 beijing 的机器,使用 hosts['beijing'] 。但如果我们程序中要频繁引用哈希表中 value ,这样就不大好了,因为 Ruby 对每一次字符串引用都会生成一个 String 对象,
累积下来这个开销是相当大的,我们可以使用 Symbol 作为 key:
1
|
hosts =
{
:beijing
=>
'machine1'
,
:shanghai
=>
'machine2'
,
:guangzhou
=>
'machine3'
,
:tianjin
=>
'machine4'
,
:shenzhen
=>
'machine5'
}
|
通常我们定义的函数的参数的个数和顺序是写死的,调用函数的时候要确保参数的个数、顺序匹配,有时候这样很不方便,使用哈希参数可以解决这个问题。