在 Ruby
中,當我們要定義一個物件時通常會像接下來的例子一樣定義它:
class Car
def initialize(color, type, wheels)
@color = color
@type = type
@wheels = wheels
end
def info
puts "這輛車子是#{@color}色的,類型為#{@type},輪子有#{@wheels}個。"
end
end
sport_car = Car.new('黃', '跑車', 4)
sport_car.info # => 這輛車子是黃色的,類型為跑車,輪子有4個。
在這段範例中,我們定義了 Car
這個類別(Class),然後我們在類別中透過定義初始化方法(Initialize)規定了方法需要傳入三個參數(Parameter),並且在 Car.new
實例化類別時需要依序
將參數傳入。最後再定義了一個方法 info
去顯示這輛車子的資訊(color
, type
, wheels
)。
當我們定義好 Car
這個類別並且有一天我們的同事需要使用這個車子類別去做一些事情的時候,你可能會需要寫一份文件就像 Ruby Doc 一樣解釋這個車子類別在實例化時需要依照順序傳入哪些參數。在這個簡單的例子中你可能會覺得,才三個參數會是有多難記?但是你有一天可能會面臨需要建立一個方法擁有七個參數以上要傳呢?你能確保每一個參數的順序你都記得嗎?萬一傳錯順序了程式可能會產生不可預期的錯誤。這時候我們就可以運用 Ruby
的一個特性來解決問題,它就是雜湊(Hash)!
在 Ruby
的世界中,雜湊是沒有順序性的,它關注的只有一對成雙 Key
和 Value
的組合,只要對 Hash
提供正確的 Key
就能取出那把 Key
所對應的值。所以在知名的網頁框架 Ruby On Rails 的方法中可以大量發現使用 Hash
的存在。現在就讓我們利用 Hash
來把剛剛的範例改寫如下:
class Car
def initialize(info)
@color = info[:color]
@type = info[:type]
@wheels = info[:wheels] || 4
end
def info
puts "這輛車子是#{@color}色的,類型為#{@type},輪子有#{@wheels}個。"
end
end
sport_car = Car.new(type: '跑車', color: '橘', wheels: 4)
sport_car.info # => 這輛車子是橘色的,類型為跑車,輪子有4個。
compact_car = Car.new(color: '黑', type: '房車')
compact_car.info # => 這輛車子是黑色的,類型為房車,輪子有4個。
還記得我們在前一個例子中,實例化方法需要依照順序傳入的三個參數嗎?利用 Hash
改寫後,現在我們的 initialize
的參數部分只規定了一個 info
,實際上這個 info
代表是一個 Hash
。我們現在從 info
取出三個 Key
分別是 :color
, :type
, :wheels
所對應得值,並將它們存入實體變數 @color
, @type
, @wheels
當中給 info
方法顯示資訊用。
這樣一來當我們將參數改為傳入一個 Hash
後,我們已經移除提供參數時會產生參數傳入對順序相依的問題,這樣就可以降低因為順序錯誤導致程式出錯的機率。再者因為當我們對 Hash
提供 Key
要取出對應的值為 nil
時,我們可以再利用一個小技巧讓值為 nil
時自動帶入預設的數值。也就是這個範例中的這段程式碼:
@wheels = info[:wheels] || 4
當我們對 info
取出輪子數量為 nil
時(也就是使用者沒有傳入 wheels: 輪子數量
),這時因為 info[:wheels] || 4
前者為 nil
時會回傳後者的特性,我們實作了當使用者沒有提供該參數時自動帶入 4
的預設值。所以範例中的 compact_car
在實例化過程中如下:
compact_car = Car.new(color: '黑', type: '房車')
compact_car.info # => 這輛車子是黑色的,類型為房車,輪子有4個。
我並沒有傳入 wheels
的值,但在執行 compact_car.info
時仍然能自動帶入輪子數量的預設值並印出 這輛車子是黑色的,類型為房車,輪子有4個。
透過 Ruby
的語言特性,我們在這篇文章探討了如何從最基本的地方處理相依性的問題。在接下來的系列文章將介紹更多的技巧喔~是不是很期待呢?