趁著再釐清觀念,打一篇加深自己的印象,順便整理一下學習隨筆。其實,龍哥在上課期間就不斷強調的是學習過程中必須去思考 “這個是什麼”、“為什麼要使用?”、 “什麼時候使用”、“使用了有什麼好處”。
所以思緒脈絡大致會遵循這幾個原則撩落去~
什麼是 String (字串) 什麼是 Symbol (符號)?
在 Ruby 裡, String (字串), Symbol (符號) 都是 Class (類別) 的一種。下面使用class
這個方法驗證。
String : A string object typically representing characters.
白話:任何以單引號或雙引號包起來的,在 Ruby 裡就是字串。例如:"cube"
, 'cube'
甚至是 ":)"
>> "cube".class
>>'cube'.class
>> ":)".class
=> String # 類別都是 String
Symbol: Symbol object represents names and some strings in Ruby.
白話:在文字前面加上冒號,就是符號。例如::cube
其實英文也夠白話,但就是第一次看會:蝦?!
>> :cube.class
=> Symbol
String (字串) & Symbol (符號) 差別?
1. String 內容可以改變,但 Symbol 不行
# 使用中括號填入數字 (index) 來取得字元
>> "cube"[1]
=> "u"
# Symbol 也 OK
>> :cube[1]
=> "u"
# 再來試著修改 String 裡面內容
>> "cube"[2] = "t"
=> "t"
# 那要怎麼知道 "b" 真的被改成 "t"
>> qq = "cube"
>> qq[2] = "t"
>> qq # => "cute"
# Symbol
>> :cube[2] = "t"
=> NoMethodError (undefined method `[]=' for :cube:Symbol)
2. Symbol 效能比較好
- 以下以
object_id
實測。(object_id
代表物件在 Ruby 裡的id
,不同的物件想當然有不同id
就像你跟我身份證號碼不一樣。)
>>"cube".object_id
=> 70264457789100
>>"cube".object_id
=> 70264457789020
>>"cube".object_id
=> 70264457788960
>> :cube
=> 1524828
>> :cube
=> 1524828
>> :cube
=> 1524828
由此可知,每次輸入 "cube"
其實代表著不同物件。 (就跟你喊 "怡君"
很多人轉頭,但每個 "怡君"
是不一樣的個體啊! ) 不過這又能證明什麼? (笑) 其實這個 object_id 也表示物件於記憶體的位置,每個 String 明顯佔了不同位置,在 Ruby 要取用時也都得再產生一組 object_id 佔一個位。反之,Symbol 從一而終都是同個物件。
- Symbol 比對速度更快
我們使用函式庫 Benchmark 來量測程式碼執行效能:
require 'benchmark' # => true
looping = 1000000000
Benchmark.measure do
looping.times do
"foo" == "foo"
end
end.total
=> 14.128060999999999
Benchmark.measure do
looping.times do
:foo == :foo
end
end.total
=> 5.308579999999999
kerker… 依照我這樣打,量測真的都要等到 total 秒數到。
最終可看出 Symbol 的處理速度快得多,因為 Symbol 單純以 object_id 來比對,而 String 則是會以字元來逐一比對。就比對方式可以推論:Symbol 的處理速度會是比較固定的,但 String 的處理時間會隨著字元的長度而增加。
String, Symbol 可以互相轉換
# String to Symbol
>> "cube".to_sym
>> %s(cube)
>> "cube".intern # 這方法用起來比較不直覺,但結果都一樣
=> :cube
# Symbol to String
>> :cube.to_s
>> :cube.id2name
=> "cube"
Symbol 特性及使用時機
Symbol 特性:
- 不可變更 (Immutable), object_id 有唯一性
- 效能比 String 好
什麼時候該使用 Symbol?
適合拿來當作 Hash 中的 Key:
>> person = { name: "Rocky", age: "40"}
=> {:name => "Rocky", :age => "40"}
又或者是設定 attr_accessor
:
class Cat
attr_accessor :name # 這裡把 :name 傳給 attr_accessor 方法
end
cat1 = cat.new
cat1.name = "Tuna"
BUT…
String 也不是被打假的,String 在 Ruby 中內建的方法比較多,操作上會更靈活。使用上有疑慮,詳閱公開說明書 Ruby.doc