前面一直提到方法,那麼到底在Ruby裡,方法(Method)是怎麼被定義的呢?
下面是,在Ruby裡,我們定義方法和呼叫方法的樣子:
def 方法名稱(參數個數隨意)
end
def say_hello_to(someone)
puts "Hi, #{someone}"
end
say_hello_to("DinDin") # "Hi, DinDin"
say_hello_to "LaLa" # "Hi, LaLa"
def say_hi_to(some = "Vegeta")
puts " I'm #{some}"
end
say_hi_to() # "I'm Vegeta"
say_hi_to("Goku") # "I'm Goku"
方法名稱後面如果接上? ,通常我們預期他會回傳true or false;
當然你也可以惡搞:
def can_fly?(age = 10)
if (age <= 10)
#true
return "I can fly, cause I'm #{age}."
else
#false
return "Oops,you're #{age}, that's why you can't fly."
end
end
p can_fly?
=> "I can fly, cause I'm 10."
p can_fly?(20)
=> "Oops,you're 20, that's why you can't fly."
這邊我們用陣列的sort 和sort! 方法來做示範:
list = [3, 2, 1, 5]
p list.sort # [1, 2, 3, 5]
p list # [3, 2, 1, 5]
p list.sort! # [1, 2, 3, 5]
p list # [1, 2, 3, 5]
有看到嗎? 當你對list使用了 sort! 方法, list就回不去了...就像變了心的女友一樣(淚目~)
Block 不是物件
Block 不是參數
Ruby裡大部分的東西都是物件, 而Block就是少數的例外。
其實在前面的部分Block 就已經出現過了:
a.each do |i|
b << i if i % 2 == 1
end
a.select {|i| i % 2 == 1}
上面在 each "方法後面" 的 do...end 和
select "方法後面" 的 { },就是所謂的Block。
會強調"方法後面"是因為:
Block 是不能單獨存在的。
Block 只是附加在方法後面,等著被呼叫的一段程式碼。
{ puts "這樣會出錯!!"}
do
puts "安捏馬港款"
end
關於block的觀念,個人覺得看code最有感,所以...
廢話不多說 ,來看code吧! :)
def say_hello
puts %Q(say hello "method")
yield
puts %Q(back to say hello "method")
end
say_hello {
puts %Q(say hello "block" with yield)
}
# say hello "method"
# say hello "block" with yield
# back to say hello "method"
如果沒有yield,寫在Block裡面的東西,是不會有反應的:
def meow
puts "霹靂!霹靂!霹靂貓!!"
end
meow {
puts "You can't see me"
}
#"霹靂!霹靂!霹靂貓!!"
def way_hi4_din
yield "什麼","什麼"
end
way_hi4_din { |n, m|
puts %Q(婆婆,我要#{n}你打#{n},這才是餵~)
puts %Q(不對,妳要#{m}我打#{m},這叫做盯~)
}
# 婆婆,我要什麼你打什麼,這才是餵~
# 不對,妳要什麼我打什麼,這叫做盯~
def test_pregnancy
if yield ("||")
puts %Q(恭喜老爺!賀喜夫人!)
else
puts %Q(換個姿勢,再來一次!)
end
end
test_pregnancy {|result|
result == "||"
}
# 恭喜老爺!賀喜夫人!
下面這段程式碼是用來展示,參數傳遞的過程:
def im_from(place)
puts "params passed from method im_from"
yield place
puts "leaving im_from"
end
im_from("Namek") { |place|
puts "params pass in to block "
puts %Q(I'm from #{place}.)
puts "prepare go back to method "
}
# params passed from method im_from
# params pass in to block
# I'm from Namek.
# prepare go back to method
# leaving im_from
但是其實,在Ruby裡面,還是有方法可以將Block物件化的;
那就是Proc,用起來的手感大概是像這樣:
shoot = Proc.new {|name| p "#{name} Shooooot!!!"}
shoot["Neo Armstrong Cyclone Jet Armstrong Cannon"]
shoot.("Neo Armstrong Cyclone Jet Armstrong Cannon")
shoot.===("Neo Armstrong Cyclone Jet Armstrong Cannon")
#上面三種呼叫方式,都會得到下面的結果
"Neo Armstrong Cyclone Jet Armstrong Cannon Shooooot!!!"
嗯?又有奇怪的東西混進程式碼了嗎?
大概是我太累產生的錯覺吧...
鐵人賽,我們明天再會!