您可能会假设您所做的声明将 Symbol 的值定义为不同于它的实际值。事实上,符号只是一个“内部化”的字符串值,它保持不变。正是因为它们是使用简单的整数标识符存储的,所以它们经常被使用,因为这比管理大量可变长度的字符串更有效。
以你的例子为例:
patient1 = { :ruby => "red" }
这应该读作:“声明一个变量 patient1 并将其定义为一个 Hash,并在此存储键下的值 'red'(符号 'ruby')”
另一种写法是:
patient1 = Hash.new
patient1[:ruby] = 'red'
puts patient1[:ruby]
# 'red'
当您进行分配时,您得到的结果与您最初分配的结果相同,这不足为奇。
符号概念可能有点令人困惑,因为它不是大多数其他语言的特性。
即使值相同,每个 String 对象也是不同的:
[ "foo", "foo", "foo", "bar", "bar", "bar" ].each do |v|
puts v.inspect + ' ' + v.object_id.to_s
end
# "foo" 2148099960
# "foo" 2148099940
# "foo" 2148099920
# "bar" 2148099900
# "bar" 2148099880
# "bar" 2148099860
每一个具有相同值的 Symbol 都指向同一个对象:
[ :foo, :foo, :foo, :bar, :bar, :bar ].each do |v|
puts v.inspect + ' ' + v.object_id.to_s
end
# :foo 228508
# :foo 228508
# :foo 228508
# :bar 228668
# :bar 228668
# :bar 228668
将字符串转换为符号将相同的值映射到相同的唯一符号:
[ "foo", "foo", "foo", "bar", "bar", "bar" ].each do |v|
v = v.to_sym
puts v.inspect + ' ' + v.object_id.to_s
end
# :foo 228508
# :foo 228508
# :foo 228508
# :bar 228668
# :bar 228668
# :bar 228668
同样,从 Symbol 转换为 String 每次都会创建一个不同的字符串:
[ :foo, :foo, :foo, :bar, :bar, :bar ].each do |v|
v = v.to_s
puts v.inspect + ' ' + v.object_id.to_s
end
# "foo" 2148097820
# "foo" 2148097700
# "foo" 2148097580
# "bar" 2148097460
# "bar" 2148097340
# "bar" 2148097220
您可以将 Symbol 值视为从内部哈希表中提取的值,并且您可以使用简单的方法调用查看已编码为 Symbols 的所有值:
Symbol.all_values
# => [:RUBY_PATCHLEVEL, :vi_editing_mode, :Separator, :TkLSHFT, :one?, :setuid?, :auto_indent_mode, :setregid, :back, :Fail, :RET, :member?, :TkOp, :AP_NAME, :readbyte, :suspend_context, :oct, :store, :WNOHANG, :@seek, :autoload, :rest, :IN_INPUT, :close_read, :type, :filename_quote_characters=, ...
当您通过冒号或使用 .to_sym 定义新符号时,此表将会增长。