iT邦幫忙

DAY 26
1

Ruby女孩:10萬.times { puts "為什麼?" }系列 第 26

Ruby女孩(26):別鬧了,方法的圓括號別亂省!

  • 分享至 

  • xImage
  •  

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

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

好的,今天來說說方法的名稱與圓括號的規定!

※ 方法的名稱

1. 慣例以小寫字母開頭(雖然大寫可以,但這會讓它看起來很像常數)
2. 方法名稱不只一個單字時,通常以底線符號分隔,例如:who_am_i
3. 方法名稱可以用一個等號、一個問號或一個驚嘆號結尾,例如:age=、include?、sort!

3-1. 一個等號:就是之前在類別時有提到的setter做法 >> Ruby女孩(19)

3-2. 一個問號:問號就很像一個問題,任何方法名稱只要以問號結尾,都會回傳一個值來回答問問題(通常是true或false)。我們之前常看到is_a?這個方法就是一個例子>>

String.is_a? Object
=> true

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

3-3. 一個驚嘆號:驚嘆號有警示的意味存在,使用的時候要很小心,一般沒有加驚嘆號的時候,會做一個副本來儲存變動後的內容;但若是有加驚嘆號的話,他會直接在原物件上修改內容。舉例來說,陣列都會有一個sort的方法,作為排序之用,以下比較sort與sort!的差異:

a = [3,1,2]

a.object_id
=> 70243998348660

a.sort.object_id
=> 70244014688220  #用另一個副本空間來做sort,不會改到原本的物件

a.sort!.object_id
=> 70243998348660  #在原本a所指到的物件上做sort,所以會修改到原本的物件

所以如果這樣看:

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,5 與 3.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女孩(25):來認識方法的定義與解除!
下一篇
Ruby女孩(27):方法的引數傳遞方式,你覺得很簡單嗎?進來小試身手看看XD
系列文
Ruby女孩:10萬.times { puts "為什麼?" }30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
dojumi
iT邦新手 4 級 ‧ 2014-10-29 15:25:33

1.()<-這個叫小括號,不叫圓括號
2.你認為含糊不清楚的東西,跟程式語言的結合律有關,請先理解,再來說含糊不清,相信真正的資深工程師會感激你

otiann iT邦新手 2 級 ‧ 2014-10-30 03:04:43 檢舉

謝謝你的提醒喔:)

  1. 其實我自己也是叫它小括號啦,只是圓括號是書中的說法,因此才延續書中的說法~(本書第189頁)
  2. 然後『含糊不清』其實也是書中給的評論,書中給出像我上面例子中這些有結合律的程式,如果省略了圓括號,除了使可讀性更削減之外,在Ruby1.8的版本中在執行程式時還會給出警告(1.9版本已將此警告刪除)。
    其實蠻不好意思的,我應該說得更清楚才不會讓你以為是我自己的見解,我初學半年,我的用詞都還是都以書中為主,謝謝你的提醒,以後我會多注意將文章寫得更清楚才不會造成含糊不清!

囧"看來寫文章也得向Ruby精神學習呢QQ要人性化之外...可讀性也很重要Orz
(ps.抱歉,我用鐵人賽的版面回完才想到那個可能不會通知你我有回,所以到這裡再回一次)

0
otiann
iT邦新手 2 級 ‧ 2014-10-30 02:45:16

@dojumi 謝謝你的提醒喔:)

  1. 其實我自己也是叫它小括號啦,只是圓括號是書中的說法,因此才延續書中的說法~(本書第189頁)
  2. 然後『含糊不清』其實也是書中給的評論,書中給出像我上面例子中這些有結合律的程式,如果省略了圓括號,除了使可讀性更削減之外,在Ruby1.8的版本中在執行程式時還會給出警告(1.9版本已將此警告刪除)。
    其實蠻不好意思的,我應該說得更清楚才不會讓你以為是我自己的見解,我初學半年,我的用詞都還是都以書中為主,謝謝你的提醒,以後我會多注意將文章寫得更清楚才不會造成含糊不清!
0
otiann
iT邦新手 2 級 ‧ 2014-10-30 02:50:43

囧"看來寫文章也得向Ruby精神學習呢QQ要人性化之外...可讀性也很重要Orz

我要留言

立即登入留言