iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 26
0
自我挑戰組

滿滿的紅寶石不拿嗎?-- 去吧!我把世界上的一切都放在那裡了! 系列 第 26

鴨子型別 <> 終於抵達阿拉巴斯坦王國!迎接我們的是 · · · 卡魯鴨? - 滿滿的紅寶石不拿嗎?

  • 分享至 

  • xImage
  •  

[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)了!


鴨子?型別?

終於要切入今天重點了!

鴨子型別是一種程式設計的風格。這種風格認為,一個物件的型別不是由這個物件所屬的類別決定,而是由「它能做什麼」來決定。

如果你看到一隻鳥走起來像鴨子,游泳起來像鴨子;叫起來也像鴨子;那麼這隻鳥就可以被稱為鴨子。

換句話說,想知道一個物件是什麼型別,看它能使用什麼方法就好。

接下來用程式碼來解釋,現在有 CatDog 兩個類別,彼此沒有相互繼承關係。

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

現在讓 miruwolf 當作帶入的參數試試:

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 在傳入 miruwolf 的當下,並沒有要求要檢查它們的型別,但是會確認它們都能執行 hungry 方法才能正常通過!

真是盡責的小鴨呢!


關於鴨子型別的的介紹就先到這邊啦!謝謝大家的觀看~


上一篇
例外處理 <> 白鬍子登場!就連海軍大將都無法擊倒的那個男人!- 滿滿的紅寶石不拿嗎?
下一篇
Self <> 真正的男子漢,連道別都不需要語言! - 滿滿的紅寶石不拿嗎?
系列文
滿滿的紅寶石不拿嗎?-- 去吧!我把世界上的一切都放在那裡了! 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言