Ruby - 深入理解Symbol
Varsion

符号(symbol)是Ruby内置类Symbol中的实例。它拥有一个字面构造器:冒号引导符,可以通过这个记号,从字面上辨认出符号与字符串、变量名、方法名等等的区别。

1
2
3
:a
:book
:"This is Chongya"

也可以通过程序的方式,在字符串上调用to_sym方法也可以通过类似的intern方法来创建一个符号:

1
2
"a".to_sym
"This is Chongya".intern

同时可以通过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
2
attr_accessor :name
attr_reader :age

通常send方法用符号作为参数,可以不使用点运算符就能发送消息给对象

1
"abc".send(:upcase)

如果事先知道完整的方法名称,一般情况不需要send方法。但是这里要注意的是,send方法可以带有一个符号参数,即使这个符号参数存储在一个变量值,或者是运行时动态确定的,该符号依然可用。

1
2
3
4
5
**思考允许符号或者字符串作为方法参数**
编写一个需要携带参数的方法时,可能会思考参数应该使用字符串或者符号,通常最好是两这都可以。
在大多数处理由用户产生的内容以及任意的字符串的时候,或者从文件中读取所包含文本的时候,是没必要这样的,这些内容不会以符号的形式出现。
但如有一个方法,他期待的参数是一个方法名或者也许是从商标或者标签的有限列表中找到的一个值,那么最好是同时允许字符串和符号的使用。
这样可以不用要求参数对象的类型必须是其中一种,并且可以避免由错误的传参而导致的错误。

符号作为哈希键值

哈希是使用键读取的数据结构:将一个值赋给一个键然后插入其中,然后通过值的引用的键取回该值。Ruby对哈希键没有任何限制。可以使用数组、类、另一个哈希、字符串或者任意想要作为哈希键的对象。但是大多情况会使用字符串或者符号。

1
2
3
4
5
6
7
hosts{
'beijing' => 'machine1',
'shanghai' => 'machine2',
'guangzhou' => 'machine3',
'tianjin' => 'machine4',
'shenzhen' => 'machine5'
}

 如果要引用 beijing 的机器,使用 hosts['beijing'] 。但如果我们程序中要频繁引用哈希表中 value ,这样就不大好了,因为 Ruby 对每一次字符串引用都会生成一个 String 对象,累积下来这个开销是相当大的。

我们完全可以使用 Symbol ,因为对于这些 key 来讲,我们用的就是名字而已,例如下面hosts[:beijing]

1
2
3
4
5
6
7
hosts = {
 :beijing => 'machine1',
 :shanghai => 'machine2',
 :guangzhou => 'machine3',
 :tianjin  => 'machine4',
 :shenzhen => 'machine5'
}

如果使用字符串作为散列键没什么问题,尤其是已经有一个字符串集合,需要将他纳入一个散列是,但是使用符号的散列键也有一些优势:

  • 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.
Comments