[Day20] 接下來要隆重登場的是,鋼!鐵!將!軍!
嗨大家好!這篇要介紹的是開放類別(Open Class)!
過去幾天,我已經學會了類別、繼承、模組、實體方法與類別方法的差異,以及方法存取的限制。而今天再來看一些有趣的東西吧!
類別—合體!
身為一隻金魚,我常常在 coding 時忘記自己有沒有寫過這個類別,一不小心就做出了兩個相同名稱的類別,但裡面各自定義的方法不同:
1 | class Robot |
這時候如果又做了一個實體 franky
出來:
1 | franky = Robot.new |
那這個實體 franky
到底是從哪個類別產生的呢? 不是很確定,
那讓它呼叫實體方法看看:
1 | franky.eye |
咦!franky
居然兩招都可以用!
難道是…?
事實上,Ruby 會把我們寫的東西看成這樣:
1 | class Robot |
居然合體啦!!!只要是同名的類別,各自定義的方法也會融合在一起!
(同名方法自然另當別論)
類別裡面什麼都不用寫也有方法可以用
之前介紹時好像沒提到 Ruby 這個有趣的特性,就拿剛剛的 Robot
做例子吧!
1 | class Robot |
現在我自己定義了一個新的類別 Robot
,可是裡面真的是超~空~一個方法都沒有。
然後 franky
能呼叫什麼方法嗎?應該不行吧?
還是來確認一下好了:
1 | franky.methods |
哇啊啊一堆方法!這些是哪裡來的?是誰偷駭進了我的電腦嗎?
不對不對這一定是在做夢,我要來測試一下!
Q1: franky
是什麼類別?
1 | franky.class |
通過第一關…沒關係再來!
Q2: franky
是整數嗎?
1 | franky.is_a?(Integer) |
好我知道很明顯不是…
啊!等等!就連一開始找方法的:
1 | franky.methods |
這個 methods
也不是我自己定義的啊!虧我還用得這麼順手!
不管是原生類別還是自定義類別,其實 Ruby 都已經先準備好很多方法著大家去使用了!這部分的原因有興趣的朋友可以先上網查 Ruby 的 Kernel
模組,有時間我會再來仔細說明!
讓我們來加點料
由於這個特性,我們就能為原生類別再添加一些自定義的方法,這個技巧也是 開放類別(Open Class) 的精髓。
譬如 Ruby 原生的 String
類別,裡面已經定義好很多給字串使用的方法:
1 | a = String.new |
現在我們來把幫 String
類別加上一個 say_hello
方法:
1 | class String |
這樣的話,剛剛 a.methods
列出來的方法裡,就會多一個我們剛剛定義的 sayhello
方法囉!
另外,在這裡的 self
指的就是呼叫方法的 receiver
本身。
Monkey Patch! 既有的方法居然也能改!
除了像剛剛那樣幫類別添加方法,我們甚至也能覆蓋掉 Ruby 原先寫好的方法,這樣的行為通常被稱作 “Monkey Patch“,這就是 Ruby 語言的一大特點:可動態修改
1 + 1 = 2
是數學上顛撲不破的真理,但我們來看個例子:
1 | 1 + 1 |
上次有提過在 Ruby 裡,其實是這樣運作:
1 | 1.+(1) |
當我們知道其實是 1
這個物件呼叫了 +
方法,再帶入 1
這個參數後,就可以自己來改寫 +
方法:
1 | 1.class |
我讓 +
這個方法變成只會回傳加上去的數字,所以這時候再使用 +
的話,就會變成:
1 | puts 1 + 1 |
得到的通通都是 1
了!數學已死!!!
今天終於來到 20 天了!開放類別就先介紹到這邊啦!後面會再提到類似的概念可能就要到淺談 Ruby 物件導向的篇章了!希望能順利完賽!
最後送大家一句金句:投資一定有風險基金投資有賺有賠使用 Monkey Patch 前應詳閱 Ruby 官方文件說明書
話已帶到,使用時請小心、保重!