Ruby Arguments 小技巧

Posted by Noel on 2015-09-15

在ruby裡,函式參數的定義與使用可以多變且靈活,這裡我們來分享一些比較特別的但實用的例子

參數的定義使用

當如果參數是要使用 hash 的話,我們都知道可以這樣用

1
2
3
4
5
6
7
8
9

def hello (options = {})
first_name = options[:first_name]
last_name = options[:last_name]
%Q(Hello, #{first_name} #{last_name})
end

hello first_name: 'Wayne', last_name: 'Rooney'
// "Hello, Wayne Rooney"

使用 Keyword Arguments

但實際可以這樣用更快,少了從options取值的步驟,而且結果是一樣的

1
2
3
4
5
6
7

def hello (first_name:, last_name:)
%Q(Hello, #{first_name} #{last_name})
end

hello first_name: 'Wayne', last_name: 'Rooney'
// "Hello, Wayne Rooney"

直接丟一個hash給它也可以,廢話

1
2
hello { first_name: 'Wayne', last_name: 'Rooney' } 
// "Hello, Wayne Rooney"

但這樣會失敗

1
2
hello first_name: 'Wayne', { last_name: 'Rooney' } 
// SyntaxError: unexpected '\n', expecting =>

必須先把merge成一個hash,或使採用更潮**運算子

1
2
hello first_name: 'Wayne', **{ last_name: 'Rooney' } 
"Hello, Wayne Rooney"

也可以與其他參數混用,但一般來說我們會把hash形式的參數擺在最後面

1
2
3
4
5
6

def man_united(manager, members, color:, name:)
%Q(Manager: #{manager}, members: #{members}, color: #{color}, name: #{name} )
end
man_united '+2', :rooney, color: :red, name: :red_devil
// "Manager: +2, members: rooney, color: red, name: red_devil "

我們也可以這樣用,讓不固定的參數可以區分成arrayhash型態

1
2
3
4
5
6
7

def test(*array, **hash)
"#{array[0]} #{array[1]} #{hash[:name]}, #{hash[:age]}"
end

test(1,2,name: :noel, age: 27, extra: :not_available)
// "1 2 noel, 27"

如果不在乎傳入什麼值的話,可以這樣定義方法

1
2
3
4
5

def foo(*)
do_something
end

這樣有什麼好處呢?假使今天我們想覆寫某個方法,在執行前先去增加某些邏輯,但又不影響到其他地方的使用。我們可以這樣寫:

1
2
3
4
5
6

def save(*)
do_something
super
end

這樣同樣是呼叫save方法,但我已經在裡面塞入某些邏輯,但又不影響其他地方對save的使用,而save依然不需要擔心到底會接到哪些參數,反正都會原封不動的還給super

參考