符号(symbol)是Ruby内置类Symbol中的实例。它拥有一个字面构造器:冒号引导符,可以通过这个记号,从字面上辨认出符号与字符串、变量名、方法名等等的区别。
1 | :a |
也可以通过程序的方式,在字符串上调用to_sym方法也可以通过类似的intern方法来创建一个符号:
1 | "a".to_sym |
同时可以通过to_s方法,轻松的将符号转换为字符串。
符号的主要特点
符号不想其他任何东西,在某些方面。他更像字符串,同时,又更像整形,主要特点是唯一性、不变性。
符号的不变性
符号是不可变的,不能添加字符,一旦字符存在,就不能修改,更不存在:abc << :d或者类似的方法。
这并不是说:adcd不存在,而是,我们不能改变:abc本身,让其追加一个:d,从而让其变成:adcd。如同整形一样,符号不能被改变。如果想要引入整数5,不能通过将对象4本身加上1来得到它,尽管可以通过调用4.+(1)来给4加上1,但是不能使得object 4 变成object 5。
相似的,尽管可以使用一个符号座位Ruby生成另外一个符号的条件,但是并不能修改指定的符号。因为。符号是一个完完全全的对象
符号的唯一性
符号是唯一的,无论何时看到:abc,看到的都是同一个对象。在这个方面相比,较字符串而言,更像是个整形。
当看到表示法"abc"出现在两个地方,他们表述的是两个字符穿对象,因为字符串构造器""创建了新的字符穿串。但是:abc总是表示相同的Symbol对象。
通过查询用于表示每个独立对象唯一性object_id就可以发现,在唯一性上的不同。

正因为符号是唯一的,所有他并没有构造器,也没有提供Symbol # new方法,用户创建一个符号所做的事情,并没有创建一个整形复杂。在任何情况下,都只能是引用该符号而已。
符号和标识符
下面的代码包含了一个Symbol对象和已发个本地变量标识符。
1 | s = :a |
将s引用为一个符号的情况是很常见的。它作为一个符号,所代表的一起除了他本身就没有更多了。而事实上,围绕着Symbol类和符号对象让人困惑的潜在因素是:符号不能代表除了自己以外的更多事物。
从某种意义上来说,一个变量名更多的是”符号性”的而不是一个符号。
符号与实践
符号最常见的用法是方法参数和哈希表。
符号作为方法参数
大量核心的Ruby方法都使用符号作为方法参数,这些方法中的大多数也可以使用字符串作为方法参数。
例如attr_*的方法
1 | attr_accessor :name |
通常send方法用符号作为参数,可以不使用点运算符就能发送消息给对象
1 | "abc".send(:upcase) |
如果事先知道完整的方法名称,一般情况不需要send方法。但是这里要注意的是,send方法可以带有一个符号参数,即使这个符号参数存储在一个变量值,或者是运行时动态确定的,该符号依然可用。
1 | **思考允许符号或者字符串作为方法参数** |
符号作为哈希键值
哈希是使用键读取的数据结构:将一个值赋给一个键然后插入其中,然后通过值的引用的键取回该值。Ruby对哈希键没有任何限制。可以使用数组、类、另一个哈希、字符串或者任意想要作为哈希键的对象。但是大多情况会使用字符串或者符号。
1 | hosts{ |
如果要引用 beijing 的机器,使用 hosts['beijing'] 。但如果我们程序中要频繁引用哈希表中 value ,这样就不大好了,因为 Ruby 对每一次字符串引用都会生成一个 String 对象,累积下来这个开销是相当大的。
我们完全可以使用 Symbol ,因为对于这些 key 来讲,我们用的就是名字而已,例如下面hosts[:beijing]
1 | hosts = { |
如果使用字符串作为散列键没什么问题,尤其是已经有一个字符串集合,需要将他纳入一个散列是,但是使用符号的散列键也有一些优势:
- Ruby处理符号更快,因此如果要大量处理散列查找的话,就会节省很多时间
- 符号作为散列键看起来会更好一些。
- Post title:Ruby - 深入理解Symbol
- Post author:Varsion
- Create time:2020-09-13 16:20:14
- Post link:https://blog.varsion.cn/post/b52e7ab6.html
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.