def abc(key , *args)
puts key
puts args.join(',')
end
> abc(1,2,3,4,5)
#=> 1
#=> "2,3,4,5"
簡單的來說可以把mehtod做類似overloading的動作,不過overloading是多個不同的method,而這個只是把傳入值打成一個array而已
不過這太簡單的,很多語言也都有實作,但,反過來怎解?把一個array打成多個傳入值
> abc(1,[2,3,4,5])
#=> 1
#=> "[2,3,4,5]" #Array
相同的code...fail,這應該不是我們想要的,而且一般而言,如果要達到這件事情,需要多個變數和判斷才能完完整整的打進去,所以這邊用新的寫法,也就是*對於Array的用法,非常類似*args,其實就是做相同的事情,把一個東西合併,也把一個東西打平
#A
> abc(1,*[2,3,4,5])
#B
> abc(1,*[2,3],*[4,5])
#C
> x = [2,3,4,5]
> abc(1,*x)
#A,B,C:
#=> 1
#=> "2,3,4,5"
上面三個結果輸出都一樣,okay,你得到它了,看起來很evil但實際是很直覺的,而*array這用法只能在傳入時使用,一般情況不能使用就是了,所以這世界真實案例是怎樣?
Rails下有個很簡單方便的例子,類似Model.where的寫法,可以傳入Hash,可是Hash就不能自己下condition(變得會只有"and"串接),也就是SQL的部份,所以如何組SQL出來?
def select_me
condition = ['kind = 3']
params.keys.each do |key|
case key
when :user_id
condition[0] += "AND id = ?"
condition << params[:user_id].to_i
when :is_locked
condition[0] += "AND `lock` = ?"
condition << params[:is_locked].to_i == 0 ? 1 : 0
when :amount_range
amount_temp = params[:amount_range].split(/_/).map{|i|i.to_i}.sort
if amount_temp.lenght == 2
condition[0] += "AND amount BETWEEN ? AND ?"
condition += amount_temp
end
end
end
@user = User.where(*condition)
end
okay...以上是demo,簡單的來說你把Array組好就把傳入值全都組好了,不用過多的暫存變數,一切都很歡樂的,然而這用法其實非常優於傳入hash再另外做解離的動作,因為你把傳入值名稱等都定義好,其實一切就變得更精確,不用另外額外寫doc來描述hash內應該需要些什麼,類似
def save_log(user_id , remote_ip , from_action , from_controller , browser_agent , session_key , cookie_token , time_now = Time.now)
#...
end
對於懶得維護doc的人而言,傳入值的變數名稱其實就已經說明了一切,且如果用IDE之類的東西,也會直接提醒,反查也一看就知道之類的...hmmm~ anyway推薦這好用的方式給您,以上
沒有留言:
張貼留言