字符串是可变的字符序列;符号(:name)是不可变的、interned 标识符——同一个符号在内存中始终是完全相同的对象。符号用作轻量级、高效的标识符(特别是哈希键),而字符串保存实际文本数据。
核心区别:身份和可变性
.object_id == .object_id
<<
.object_id == .object_id
.frozen?
每个字符串字面量都会创建一个新对象,但符号是 interned 的——:hello 在内存中始终是完全相同的对象,无论出现多少次。符号也是不可变的。
Strings: each "name" allocates a new object → more memory, slower comparison (char by char)
Symbols: :name is ONE shared object → memory-efficient, fast comparison (by identity)
→ Symbols are ideal as identifiers used repeatedly (hash keys, method names, options).
# SYMBOLS — for identifiers: hash keys, method names, options, fixed labels
user = { name: "Ann", role: :admin } # symbol keys (the idiom)
send(:upcase) # method name as a symbol
status = :active # a fixed label/state
# STRINGS — for actual text DATA that you display, manipulate, or that varies
name = "Ann Smith" # real text content
message = "Hello, #{name}" # building/interpolating text
user_input = gets.chomp # data from outside
对标识符使用符号(哈希键、选项名称、状态、方法名称——固定的、重复出现的标签),对实际文本数据使用字符串(你显示的、操作的或来自用户的内容)。
"hello".to_sym # :hello
:hello.to_s # "hello"
理解字符串与符号的区别很重要,这是 Ruby 特有的知识,因为许多其他语言缺少符号这个特性,而适当地使用它们是惯用的 Ruby。
关键区别在于符号是 interned 且不可变的(:name 在内存中始终是同一个对象,不可变),而字符串是可变的,每个字面量都是一个新对象。
这给符号作为标识符提供了内存和性能优势:它们只被分配一次并共享(重复使用时内存高效),并且通过身份进行比较(快速)而不是逐字比较。
实用指南——对标识符使用符号(哈希键、方法名称、选项标签、固定状态——作为标签重复使用的事物)和对实际文本数据使用字符串(你显示的、操作的或从用户接收的内容)——这是重要的惯用 Ruby,影响性能和清晰度。
符号哈希键({ name: "Ann" })是 Ruby 和 Rails 中的约定,对固定标识符使用符号而不是字符串既高效又符合约定。
理解何时使用每个、符号的 interning/不可变性以及它们作为标识符的效率是基础的、经常应用的 Ruby 知识——这是新手的常见困惑点(为什么要两者都有?),而掌握这种区别(符号作为高效 interned 标识符,字符串作为可变文本数据)对编写惯用、高效的 Ruby 至关重要,也是反映对这一独特 Ruby 特性理解的常见面试话题。