[Day26] 卡魯鴨:我跑遍了沙漠,好渴啊!
自從學了 Ruby ,就常聽到別人在說 鴨子型別(Duck Type),可是卻一直沒有弄得很懂,今天決定來了解什麼是鴨子型別!
開始囉!
型別,是一種為了讓資源(位元組)更有效率地被利用而規劃的概念。簡單來說,每筆資料都有自己所屬的型別,譬如:整數、字串、陣列等等...
在鐵人賽第3天裡,我列出了一些 Ruby 常見的資料型別,各自做了簡單的介紹。但型別遠沒有這麼簡單啊!
Ruby 常被稱作是一種強型別的語言,然而,有強就有弱,判定標準在於語言能否自動轉換型態:像是 JavaScript,經常會偷偷地把變數轉換成可以被執行的資料型態(讓我覺得十分困擾)不過到了 Ruby 這裡,就會被仔細地檢查型別,型別不符的話則會發生錯誤。
還記得用怎麼類別產生實體物件嗎?產生實體物件也是一種將某個型別實體化的過程。
String.new("卡魯鴨")
=> "卡魯鴨"
String.new(123)
TypeError (no implicit conversion of Integer into String)
接著,我們可能還要了解「動態型別」是什麼。
Ruby 被認為一種 動態型別(Dynamically Typed) 的語言,「動態、不固定」的意思是 在命名變數時,不用先宣告是哪種型別
有了動態型別,我們就能寫出較為簡潔的程式碼。同時,也因為不用先提供型態資訊,因此變數型態是可以改變的。
舉個例子,比方說先把字串"卡魯鴨"
指定給區域變數 a
:
a = String.new("卡魯鴨")
=> "卡魯鴨"
a = 123
a
=> 123
變數 a
的型別被換成整數(Integer)了!
終於要切入今天重點了!
鴨子型別是一種程式設計的風格。這種風格認為,一個物件的型別不是由這個物件所屬的類別決定,而是由「它能做什麼」來決定。
如果你看到一隻鳥走起來像鴨子,游泳起來像鴨子;叫起來也像鴨子;那麼這隻鳥就可以被稱為鴨子。
換句話說,想知道一個物件是什麼型別,看它能使用什麼方法就好。
接下來用程式碼來解釋,現在有 Cat
和 Dog
兩個類別,彼此沒有相互繼承關係。
class Cat
def hungry # 同樣名稱的方法
puts "喵~肚子餓了!"
end
end
class Dog
def hungry # 同樣名稱的方法
puts "汪!肚子餓了!"
end
end
再建立一個 Pet
類別,同時定義一個 who_is_hungry
方法可以傳入 name
,並讓 name
呼叫 hungry
執行:
class Pet
def initialize
end
def who_is_hungry(name)
name.hungry
end
end
接著做出幾個實體:
miru = Cat.new
wolf = Dog.new
pet = Pet.new
現在讓 miru
和 wolf
當作帶入的參數試試:
pet.who_is_hungry(miru)
pet.who_is_hungry(wolf)
# 印出
喵~肚子餓了!
汪!肚子餓了!
用其他參數或另外的實體試試:
pet.who_is_hungry(123)
=>NoMethodError (undefined method `hungry' for 123:Integer)
fish = Pet.new
pet.who_is_hungry(fish)
=> NoMethodError (undefined method `hungry' for #<Pet:0x00007fd74407d0a0>)
可以看到 pet.who_is_hungry
在傳入 miru
或 wolf
的當下,並沒有要求要檢查它們的型別,但是會確認它們都能執行 hungry
方法才能正常通過!
真是盡責的小鴨呢!
關於鴨子型別的的介紹就先到這邊啦!謝謝大家的觀看~