Symbol是什麼?
在ruby的撰寫過程中,時常看到:name, :title
等前面帶有冒號的用法,它就是symbol,中譯為符號。
Ruby在處理每一個物件時,會在記憶體中產生一組新的object_id,所以每一個東西都不相同,但Symbol 即使被重複使用,也都是同一個物件,object_id 不會變,不會消耗多餘的記憶體。
ruby官方api對symbol下的註解及example:
Symbol objects represent names inside the Ruby interpreter. They are generated using the
:name
and:"string"
literals syntax, and by the variousto_sym
methods. The same Symbol object will be created for a given name or string for the duration of a program's execution, regardless of the context or meaning of that name. Thus ifFred
is a constant in one context, a method in another, and a class in a third, the Symbol:Fred
will be the same object in all three contexts.假設 Fred 在一個 context 中是一個constant(常數),在一個 context中是method(方法),同時是另一個 context 的class(類別), Symbol:Fred 全都是相同的物件,會得到同個object_id。
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
與Variable(變數)有何不同?
ruby是個物件導向的程式語言,每一個變數、數字、文字都是物件,symbol也不例外,可將它看作是「帶有名字的物件」,本質上就是「值」,不需要也不能指向任何東西,變數則是指向某物件的名字,無法單獨存在。而且你也沒辦法直接拿 Symbol 來當變數,像這樣會出現語法錯誤:
:name = “Phil Lee” #出現錯誤碼:syntax error, unexpected ‘=’, expecting end-of-input
與String(字串)有何不同?
1. string的內容可以變,symbol不行
相似之處在於,他們都可以使用字元方法如.length及.upcase等,也都可以使用中括號 + 索引來取得其中某個字元,但如果想修改symbol的內容,會發生語法錯誤,因為 Symbol 類別並沒有 []= 這個方法。
:lakers.length
=> 6
:lakers.capitalize[0]
=> "L"
:lakers[0] = "k"
undefined method `[]=' for :lakers:Symbol
2. symbol的提取效率比string好
上面提到,相同的string對ruby來說是不同物件,而相同的symbol則對應到記憶體中的相同物件。不同symbol 在做比較的時候,是直接比對這兩顆物件的 object_id是否相同,而字串比較則是一個字母一個字母逐一比對。所以在效率上來說,string在做比較的時間複雜度會隨著字母的數量而增加,但 Symbol 因為只比較是不是同一個物件,所以它的複雜度是不變的。
5.times do
puts "lakers".object_id
end
=>47397526282660
47397526282360
47397526285620
47397526212580
47397526212520
5.times do
puts :lakers.object_id
end
=>1031708
1031708
1031708
1031708
1031708
3. string跟symbol間可以互相轉換
string可透過.to_sym及.intern轉換成symbol。
"lakers".to_sym => :lakers "lakers".intern => :lakers
symbol則可透過.to_s及id2name轉換成string。
:lakers.to_s => "lakers" :lakers.id2name => "lakers"
4. 如果把 String 給”冰凍”(freeze)起來,它便不可修改,object_id 也會是同樣的。
3.times do
puts "hello".freeze.object_id
end
# => 70314415546380
# => 70314415546380
# => 70314415546380
Symbol的使用時機?
Strings are used to work with data.
Symbols are identifiers.
You should use symbols as names or labels for things (like methods) &
use strings when you care more about the data (individual characters).
當我們需要內容是不可變動時,可使用symbol,因為 Symbol具有不可變(immutable),像標籤一樣的特性,以及它的查找、比較的速度比字串還快,它很適合用來當 Hash 的 Key。
hash = {a: 1, b: 2, c: 3}
另外有的方法的參數是用字串,有的是用 Symbol,有的是兩種都能用,那該怎麼知道該用哪一種? 可參考ruby官方api。
參考資料:
Ruby 語法放大鏡之「有的變數變前面有一個冒號(例如 :name),是什麼意思?」 | 高見龍