Ruby 學習筆記-Symbol(符號)


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 if Fred 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 2.7.2

Ruby 語法放大鏡之「有的變數變前面有一個冒號(例如 :name),是什麼意思?」 | 高見龍

What Are Ruby Symbols & How Do They Work? - RubyGuides

[Ruby] Symbol(符號)

#Ruby on Rails






你可能感興趣的文章

【單元測試的藝術】Chap 1: 單元測試基礎

【單元測試的藝術】Chap 1: 單元測試基礎

[PHP] 常見網路攻擊及防範方法

[PHP] 常見網路攻擊及防範方法

ImageView同寬不同長

ImageView同寬不同長






留言討論