鐵 人
Ruby女孩(26):別鬧了,方法的( )別亂省!
2014.Oct.26

接續昨天的話題,昨天我們有提到,定義一個方法時要注意

  1. 方法的名稱有規定寫法,待下方再做解釋
  2. ( )通常可省略,但也有不可省略之時,也是待下方再做解釋
  3. ( )中的參數,可直接作為方法程式碼中的變數(參數所提供的值,為調用方法時所給的引數)

好的,今天來說說方法的名稱與( )的規定!

方法的名稱

  1. 慣例以小寫字母開頭(雖然大寫可以,但這會讓它看起來很像常數)
  2. 方法名稱不只一個單字時,通常以底線符號分隔,例如:who_am_i
  3. 方法名稱可以用一個等號、一個問號或一個驚嘆號結尾,例如:age=include?sort! - 一個等號:就是之前在類別時有提到的setter做法 » Ruby女孩(19) - 一個問號:問號就很像一個問題,任何方法名稱只要以問號結尾,都會回傳一個值來回答問問題(通常是true或false)。我們之前常看到is_a?這個方法就是一個例子(範例1) - 一個驚嘆號:驚嘆號有警示的意味存在,使用的時候要很小心,一般沒有加驚嘆號的時候,會做一個副本來儲存變動後的內容;但若是有加驚嘆號的話,他會直接在原物件上修改內容。舉例來說,陣列都會有一個sort的方法,作為排序之用,以下比較sortsort!的差異(範例2a,2b)
#範例1
String.is_a? Object  
=> true  

問題:String是一個物件嗎? 答案:是的!

#範例2a
a = [3,1,2]  
  
a.object_id  
=> 70243998348660  
  
a.sort.object_id  
=> 70244014688220  #用另一個副本空間來做sort,不會改到原本的物件  
  
a.sort!.object_id  
=> 70243998348660  #在原本a所指到的物件上做sort,所以會修改到原本的物件  

所以如果這樣看:

#範例2b
a = [3,1,2]  
  
a.sort  
=> [1, 2, 3]  
  
a  
=> [3, 1, 2]  #原本a所指到的物件並未修改  
  
a.sort!  
=> [1, 2, 3]  
  
a  
=> [1, 2, 3]  #原本a所指到的物件被改掉了!  

運算符方法

Ruby 中有很多運算符,例如+*…這些其實都是方法,我們平常看到的1 + 2其實是因為1有一個方法叫做+,它也可以這樣寫:

1.+(2)  
等同於  
1.+2  
等同於  
1+2  

1+2當然是最簡便的寫法,不過也許很多人用太習慣了,會不知道原來這也是利用方法的定義來做的,我們甚至可以惡搞改掉+的方法定義(參考自Ruby也可以這樣寫):

class Fixnum  
  alias :fake_plus :+ #alias用法隨即介紹,請往下看  
  def +(num)  
    self.fake_plus(num).-(num)  
  end  
end  

Fixnum本身就有+這個方法,我們偷偷把+的定義改成+完再-,結果:

1+2  
=> 1  
  
40+88  
=> 40  

不知道的人可能以為自己的加法壞掉了,怎麼加都沒變,原來是+的定義被改掉了XD

方法的別名

Ruby 中很多方法都有別名,這是一個非常人性化的做法,常常可以讓整串code 更符合語意,例如以前曾介紹過.include?.member?.cover?這三個方法就是同義的方法,都在看一個物件有沒有被包含:

rubyist = ["Annie","Linda","Ironman"]  
rubyist.member? "Annie"  
=> true  
  
high_score = (82..98)  
high_score.cover? 88  
=> true  

上面的方法定義相同,但會有比較自然語意的方法!

除了語意之外,還有一種比較實際的理由,就是可以用alias的方式來幫擴充或修改既有的方法! alias寫法:『alias 別名 原名』,例如剛剛提到的:

alias :fake_plus :+  

# :fake_plus 是我幫他取的別名
# :+ 是原本的名字

我們再看一個例子:

class Test  
  def hello  
    "我是舊方法"  
  end  
  
  alias old_method hello  
  
  def hello  
    "我來擴充新東西了>>" + old_method  
  end  
end  

步驟一:在類別中定義舊方法 步驟二:幫舊方法取別名 步驟三:用舊方法的名字定義新內容,還可以用舊方法的別名呼叫它!

執行看看:

a = Test.new  
=> #<Test:0x007fa873806ee8>  
  
a.hello  
=> "我來擴充新東西了>>我是舊方法"  

方法與( )

方法後面跟的( )是可以省略的,除了少數特例之外!

puts "Hello" 其實是 puts ("Hello") 的省略版本。

3.between? 1,53.between?(1.5) 也是一樣的!

在方法定義的時候,也可以省略:

def sum(x,y)  
  x+y  
end  
  
def sum x,y  
  x+y  
end  

上面這兩個也是一樣的! 好的,那到底什麼時候不能省略呢?

例如函數之間巢狀使用的時候:

f(g(h(x,y)))  
f(g(x),y)  

這不加括號應該很恐怖吧…

f g h x,y  

誰看得懂==

還有一些容易顯得含糊不清的寫法,都建議主動加上括號:

def pp(num)  
  num*num  
end  
  
pp(2+2)*2  
=> 32  
  
pp (2+2)*2  
=> 64  

可以看到下面兩個呼叫pp方法的寫法只差有沒有空格,可是卻有不同的結果,因為它得判斷num到底是引入哪個參數,是(2+2),還是(2+2)*2,所以為了寫清楚,可以改成:

pp((2+2)*2)  

這樣就比較不會搞錯!

至於引數的內容也有很多可以講呢!有待明日分曉XD


26天了!

“The problem is not the problem. The problem is your attitude about the problem.”

Ruby女孩(27):方法的引數傳遞方式,你覺得很簡單嗎?進來小試身手看看XD
2014.Oct.27
Ruby女孩(25):來認識方法的定義與解除!
2014.Oct.25
comments powered by Disqus