[ Ruby ] Methods 後面有!驚嘆號 (exclamation marks)

Chao Wu
4 min readMay 16, 2019

--

這個有驚嘆號的東西會動耶!(+d Spin|スピン コマ)

我一開始是在 Stack Overflow 查找 String 的 reverse method(將字串內容反置的方法)時,看到下面的回覆:

我照著這個回覆自己試著做了一遍後,好奇想著:

「有沒有驚嘆號會有什麼變化嗎?」

就發現有加!驚嘆號和沒加!驚嘆號會有不一樣的結果。

沒有!驚嘆號

在 013 > 中對 say_hello 這個對象使用 reverse 這個方法後,顯示結果為 => “!gninrom dooG”,之後再對 say_hello 使用 p 方法後發現,say_hello 仍保有本身的內容,並沒有被改變。

有!驚嘆號

在 017 > 中對 go_sleep 這個對象使用 reverse! 這個方法後的結果確實把字串內容反置了,但再一次對 go_sleep 使用 p 方法後會發現 go_sleep 的內容變成「對象的內容被反置後的結果」,因此,使用有!驚嘆號的方法將會永久改變方法作用對象的內容。

那如果不想改變對象本身,但又想要能夠使用被改變的內容,該怎麼辦呢?

可以將改變內容的結果指派給另外一個變數:

從上方看到 051 > 中仍保有 mark 本身的內容,而 052 > 中的 little_mark 也確實接收到 mark 經由 downcase(將字串轉成小寫的方法)後的結果,並且能夠以 little_mark 來使用小寫的字串內容。

我們只是長得很像而已!

可以發現在查找 Ruby 的 Methods 文件時,可以看到許多與 reverse 和 reverse! 一樣成對的 methods,差別只在於有沒有後面的!驚嘆號。

要注意的是,reverse 和 reverse! 是兩個方法,而不是 reverse 後面加上!驚嘆號。簡單說 reverse 和 reverse! 是長得很像的兄弟,而不是 reverse 這個人拿了一個!驚嘆號的拐杖。

結論

  • 沒有!驚嘆號

方法只會作用在當下的對象本身,而這就是一般我們在使用方法的方式,這樣的方式在 Ruby 中稱為「安全方法 (safe methods)」,若要重複使用或是不想改變對象本身的內容的話,則可以用一個變數去接收「該對象使用方法後的結果」。

  • 有!驚嘆號

方法會去修改作用對象本身的內容,而在 Ruby 中有!驚嘆號的方法又稱作「危險方法 (dangerous methods)」。因為有!驚嘆號的方法會永久改變作用對象本身的內容,所以使用前要確保自己之後不會想再使用作用對象原本的內容。

但有!驚嘆號的方法能幫助我們在後續追蹤程式碼時,可以一眼看出哪裡有內容被修改過。

--

--

Chao Wu

blog_stories = 4; ( blog_stories >= 10 ) ? ‘Congratulation! Level up!’ : ‘Keep fighting! Chao Wu!’