接續上一篇類別(Class), 這篇來説說模組(Module)吧!

Module

Module 的起手式:

module Skill03
  def surf
    # do something
  end
end

如果還記得 Class 的起手式,會發現,寫起來好像一樣 @@?

Module & Class

為了先切割兩者,就先來看看到底 Module & Class 什麼關係? 有什麼差別?

Class.superclass
=> Module

在 irb 試著輸入這樣,你會發現 Class 的上層是 Module

那差別呢?

Class.instance_method - Mudule.instance_method
=> [:allocate, :superclass, :new]

Ruby 告訴我們,ClassModule 多三個方法,正因為這樣所以 Module 不能 new 新實體、無法繼承。(好奇 allocate,可以看看[這篇][Ruby allocate method])

How to Use Module?

初步認識 Module & Class 關聯與差別,接著來看看怎麼使用:

module Skill03
  def surf
    puts "Aloha"
  end
end

class Pikachu
  include Skill03   
end

pikachu = Pikachu.new
pikachu.surf
=> Aloha

Pikachu 類別中使用 include 就能將 Skill03 模組加入,而一個新的 Pikachu 實體就能使用模組裡的衝浪了。

有趣的地方是,模組可以在不同類別間使用。假設我想讓柯P可達鴨學會衝浪可以這樣做:

class Psyduck
  include Skill03
end

kp = Psyduck.new
kp.surf
=> Aloha

include, extend?

剛剛用 include 讓想學衝浪的皮卡丘跟可達鴨都學會了,然後你會發現 surf 的作用對象都是實體(instance):pikachu, kp。換句話說,使用 include 會讓衝浪變成是實體方法(instance method)。

Pikachu.surf
Psyduck.surf
=> NoMethodError

相對地,使用 extend 可以使衝浪變成是類別方法(class method),同樣的無法作用於實體(instance)。(關於實體方法與類別方法,剛好在 Class 有稍稍提到。)

class Psyduck
  extend Skill03
end

Psyduck.surf
=> Aloha
kp.surf
=> NoMethodError

When to Use?

如果有玩過掌上型遊戲機(GameBoy)的神奇寶貝,那應該知道衝浪是需要透過招式機學會的。是的,模組就像是招式機,只要 include,連電氣系的皮卡丘都可以衝浪。無法因為是水系神奇寶貝就能繼承衝浪。

不適用類別繼承的原因大概就像皮卡丘不用為了會衝浪而轉系當水系神奇寶貝吧。(這樣就不能使出招牌十萬伏特了…QQ)

Reference

後話:include, extend 加上 prepend 都與繼承鍊這個概念有關,之後有機會一定再做探討。