Symbol VS String

by Aaron • 10/22/2024, 5:21:42 PM

Ruby 常常看到在表示一個字串的時候有些地方用 Symbol, 有些地方卻用 String, 到底 Ruby 中的 Symbol 和 String 有什麼不同?什麼時候應該用 Symbol?

可變性

String 建立後是可以對某個字做更改的, 但是 Symbol 並不行

string = "string"
string[0] = "S"
# String

symbol = :symbol
symbol[0] = :S
# NoMethodError (undefined method `[]=' for :symbol:Symbol)

甚至我們細看這兩個所提供的 methods, 可以看到 Symbol 也沒有提供許多 BANG! methods 例如 downcase!, capitalize!

string.methods - symbol.methods
# [:unicode_normalize, :unicode_normalize!, :ascii_only?, :to_r, :unpack, :encode!, :unpack1, :%, :include?, :*, :+, :count, :partition, :+@, :-@, :<<, :to_c, :sum, :insert, :[]=, :bytesize, :succ!, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :scrub!, :scrub, :undump, :byteslice, :dump, :downcase!, :hex, :capitalize!, :upcase!, :lines, :codepoints, :split, :swapcase!, :bytes, :oct, :prepend, :grapheme_clusters, :concat, :reverse, :reverse!, :to_str, :crypt, :ord, :strip, :to_i, :to_f, :center, :gsub, :ljust, :chars, :delete_suffix, :sub, :rstrip, :scan, :chomp, :rjust, :lstrip, :chop!, :delete_prefix, :chop, :sub!, :gsub!, :delete_prefix!, :chomp!, :strip!, :lstrip!, :rstrip!, :squeeze, :delete_suffix!, :tr, :tr_s, :delete, :each_line, :tr!, :tr_s!, :delete!, :squeeze!, :each_byte, :each_char, :each_codepoint, :each_grapheme_cluster, :b, :slice!, :rpartition, :force_encoding, :valid_encoding?, :unicode_normalized?, :encode]

儲存方式

相同 Symbol 只會有一個物件, String 每次建立都是新的物件

foo = "string"
foo.object_id
# 220
bar = "string"
bar.object_id
# 240

foo = :symbol
foo.object_id
# 902748
bar = :symbol
bar.object_id
# 902748

比較

相同的 Symbol 在記憶體會是同一個, 那當然相較 String 比較省記憶體, 那速度方面呢?


n = 100_000_000
results = Benchmark.bm(15) do |x|
  x.report("symbol:") { n.times { :foo } }
  x.report("string:") { n.times { "foo" } }
  x.report("symbol compare:") { n.times { :foo == :foo } }
  x.report("string compare:") { n.times { "foo" == "foo" } }
end

#                       user     system      total        real
# symbol:           1.899853   0.003015   1.902868 (  1.904602)
# string:           3.735612   0.006903   3.742515 (  3.742530)
# symbol compare:   2.165240   0.004339   2.169579 (  2.169611)
# string compare:   6.695739   0.017175   6.712914 (  6.714193)

可以看到

總結

比較StringSymbol
可變性可變不可變
儲存方式每次建立都是新的物件相同 Symbol 只會有一個物件
用途動態內容(如使用者輸入)固定識別符(如 Hash 鍵)

References

© 2025 Aaron Li. All Rights Reserved.