15

我第一次尝试学习 Ruby 是在 2 年前,现在我又开始了。我停止的原因是因为我无法理解 Symbol 类。现在我又在同一点上,完全迷失在何时以及为什么使用符号。我已经阅读了 Stackoverflow 上的其他帖子,并在 Google 上搜索了一些解释。但我还不明白。

首先,我认为符号只是一种创建某种“命名常量”的方法,而不必经历与 Java 相同的过程。

:all 

而不是制作具有任意值的常量public static final String ALL = 8;

attr_accessor :first_name etc. 但是,当您在例如Are Symbols 只是一个轻量级的String 类中使用它时,它没有多大意义?我在理解我应该如何解释、何时以及如何在我自己的类和框架中使用符号时遇到问题。

4

5 回答 5

34

简而言之,符号轻量级字符串,但它们也是不可变且不可垃圾回收的。

您不应该数据处理任务中将它们用作不可变字符串(请记住,一旦创建符号,它就不能被销毁)。您通常使用符号来命名事物。

# typical use cases

# access hash value
user = User.find(params[:id])

# name something
attr_accessor :first_name

# set hash value in opts parameter
db.collection.update(query, update, multi: true, upsert: true)  

我们先举个例子,params[:id]。在一个中等大小的 Rails 应用程序中,可能有成百上千的那些分散在代码库中。如果我们使用字符串访问该值params["id"],则意味着每次都分配新的字符串(并且之后需要收集该字符串)。如果是符号,实际上到处都是相同的符号。减少内存分配器、垃圾收集器甚至你的工作(:比打字更快""

如果你有一个简单的单字字符串,它经常出现在你的代码中,并且你没有对它做一些时髦的事情(插值、gsub、大写等),那么它很可能是一个很好的候选者。

但是,这是否仅适用于用作实际程序逻辑的一部分的文本(例如命名),而不适用于您在实际运行程序时获得的文本……例如来自用户/网络的文本等?

我想不出一个我想将数据从用户/网络转换为符号的情况(也许除了解析命令行选项)。主要是因为后果(一旦创建的符号永远存在)。

此外,许多编辑器为符号提供不同的颜色,以在代码中突出显示它们。看看这个例子

符号与字符串

于 2012-07-12T08:09:53.257 回答
12

O'Reilly Ruby Cookbook (p. 15) 引用 Jim Weirich 的话说:

  • 如果对象的内容(字符序列)很重要,请使用字符串。
  • 如果对象的身份很重要,请使用符号。

符号通常用作散列键,因为键的身份很重要。使用某些方法(如Object#send )传递消息时也需要符号。

于 2012-07-14T23:57:27.773 回答
8

Ruby 实现通常有一个表,其中存储所有类、方法和变量的名称。它指的是通过表中的位置说一个方法名称,避免昂贵的字符串比较。但是您也可以使用此表并为其添加值:symbols.

如果您编写的代码使用字符串作为标识符而不是其文本内容,请考虑符号。如果您编写的方法期望参数是“男性”或“女性”,请考虑使用:maleand :female。比较两个符号是否相等比字符串快(这就是符号成为良好哈希键的原因)。

于 2012-07-12T13:54:00.093 回答
5

符号用于命名语言中的事物:类的名称、方法的名称等。这些非常类似于字符串,只是它们永远不会被垃圾收集,并且对相等性的测试进行了优化,使其非常快速。

Java 实现有一个非常相似的东西,除了它不能用于运行时使用。我的意思是,当您编写 java 代码时obj.someMethod(4),编译器会将字符串“someMethod”转换为嵌入到 .class 文件的查找表中的符号。这些符号就像不是垃圾收集的“特殊”字符串,并且可以非常快速地比较是否相等。这几乎与 Ruby 相同,只是 Ruby 允许您在运行时创建新符号,而 Java 只允许在编译时创建。

这就像创建新方法一样——Java 在编译时允许这样做;Ruby 在运行时允许它。

于 2012-07-17T10:38:28.340 回答
1

在 ruby​​ 版本 2.2 符号 GC 被删除后,所以现在凡人符号,即当我们将字符串转换为符号时 ("mortal".to_sym) 会从内存中清除。

看一下这个:

require 'objspace'
ObjectSpace.count_symbols
{
  :mortal_dynamic_symbol=>3,
  :immortal_dynamic_symbol=>5,
  :immortal_static_symbol=>3663,
  :immortal_symbol=>3668
}

来源:https ://www.rubyguides.com/2018/02/ruby-symbols/

于 2020-02-02T17:53:50.763 回答