使用Ruby符号

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

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

:all 

而不是使用任意值创建常量public static final String ALL = 8;

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

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

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

 # 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,upcase等),那么它很可能是一个很好的候选者。

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

我想不出一个案例,我想将数据从用户/ web转换为符号(可能除了解析命令行选项)。 主要是因为后果(曾经创造过的符号永远存在)。

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

符号vs字符串

O’Reilly Ruby Cookbook (第15页)引用Jim Weirich的话说:

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

符号通常用作散列键,因为它是重要键的标识 。 使用Object#send等特定方法传递消息时也需要符号。

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

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

符号用于命名语言中的东西:类的名称,方法的名称等。这些非常类似于字符串,除了它们永远不会被垃圾收集,并且对相等性的测试被优化为非常快。

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

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