ruby-on-rails - Symbol 对象上的 Ruby 文档具有误导性
问题描述
我是 Ruby 的新手,和其他人一样,我很难理解 Ruby 符号。我知道这个主题已经被多次提出,但我相信这篇文章可能与其他文章略有不同。如果没有,我很抱歉。以文档中的这段代码为例。
module One
class Fred
end
$f1 = :Fred
end
module Two
Fred = 1
$f2 = :Fred
end
def Fred()
end
$f3 = :Fred
$f1.object_id #=> 2514190
$f2.object_id #=> 2514190
$f3.object_id #=> 2514190
我的抱怨是它让我们认为类、模块或函数与:Fred
符号之间存在联系。难怪人们会问诸如“我可以为符号分配值”之类的问题,或者该符号是对另一事物的引用。
这段代码增加了混乱:
class TestController < ApplicationController
layout :which_layout
def index
...
end
private
def which_layout
if condition
"layout1"
else
"layout2"
end
end
end
起初,我以为是对函数的引用,但实际上只是布局方法的行为会根据我们是否传递 a String
(模板名称)或 a Symbol
(调用符号指定的方法)而有所不同如文档所述。(它是否寻找method.to_sym
与我们作为参数传递的符号等效的 a ?)
然而,我相信我读到的是,在创建一个类时,他的符号对应物将被自动创建,即 :Fred 将已经存在于后续调用中。但仅此而已?
我的问题是:为什么他们必须包含一个类、一个变量和一个函数来说明这一点?上下文?那为什么要同名呢?为什么不这样做:
$f1 = :Fred
$f2 = :Fred
$f3 = :Fred
$f1.object_id #=> 2514190
$f2.object_id #=> 2514190
$f3.object_id #=> 2514190
解决方案
当您使用符号时,Ruby 会查看现有符号的列表,因此当您重用符号时,您不会在内存中创建单独的对象。
irb(main):006:0> :foo.object_id == :foo.object_id
=> true
您可以将此与字符串进行对比:
irb(main):007:0> "foo".object_id == "foo".object_id
=> false
这与它们比较便宜的事实相结合,使得符号像哈希键一样有效。
这个非常令人困惑的例子表明,符号不是作用域私有的——符号表是全局的。如果使用实例变量而不是全局变量,那就不会那么混乱了。我认为它还试图证明模块和类名是常量。
irb(main):016:0> Fred = Module.new do; end # this is the same as using the module keyword
irb(main):017:0> Fred.object_id != :Fred.object_id
=> true
这意味着这Fred
是对模块的引用,:Fred
而是一个值(一个符号)。
像字符串这样的符号是一个值,因此不能用作参考。这非常像true
,false
并且nil
是单例对象。
irb(main):008:0> true.class
=> TrueClass
irb(main):09:0> true.object_id == true.object_id
=> true
# you can even use the singletons as hash keys
irb(main):010:0> { true => 1, false => 2, nil => 3 }[true]
=> 1
Rails 示例并没有那么复杂。:which_layout
只是传递给布局方法的参数。布局方法有一个条件,它使用 Object#send 动态调用 :which_layout 方法(如果存在)。而是直接使用字符串参数来构造 glob。
推荐阅读
- sql - 下面的 SQL 查询中的内部查询是做什么的?min 函数中有两个 datetime 函数是什么意思?
- python-3.x - 在python 3中从对象类型[]转换熊猫列
- android - 在 Retrofit 2 中调用 URL 时出现 HTTP 400 错误
- android - 无法在设备上应用更改:DEVICE####。错误是:无法读取未定义的属性“env”
- ios - 如何将结构或类对象附加到 SCNNode
- ruby-on-rails - Rails 5 尝试将空字符串保存为 nil
- angular - Angular 表单一次显示一条错误消息
- knockout.js - Dynamic Add New Row Using knockout js
- node.js - 在 NestJS 中为 Pug 设置“basedir”选项
- docker - 如何在 dockerfile 中使用 .ENV 文件中的变量?