這篇就來好好了解一下 Ruby 中的模組吧,先來用個我最愛的超級英雄蜘蛛人當成例子
以前面人類類別的例子,我希望他可以有吐絲的能力來當蜘蛛人,可能會想用以下這些做法:

  1. 建立一個蜘蛛類別並且帶有吐絲功能,然後再叫人類類別去繼承
  2. 在人類類別裡面定義一個吐絲功能

第 1 種的方式感覺在邏輯上比較奇怪,人為了吐絲就要去繼承蜘蛛,感覺就跟原本設定的類別有點衝突;第 2 種是直接寫在內部確實也可以達到同樣效果,但如果其他類別也需要用到這項能力就要另外在寫,沒辦法抽出來共用。

如果我們能夠把這些超級能力抽出來,需要使用再引入,不是很好嗎?
於是就有了模組的概念可以來解決這樣的狀況!

模組定義與使用

module 後面接上模組名稱,命名規則與 class 相同,使用駝峰大寫,下面就可以定義內部要有的方法。
如果在其他類別內要引用就使用 include

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定義吐司模組
module spinning
def spin
puts "我會吐絲啦!"
end
end

# 引入模組到人類類別
class Human
include spinning # 引入吐絲模組
end

Sean = Human.new
Sean.spinning # 我會吐絲啦!

在類別中引入模組就可以讓新建立的實體 Sean 直接可以使用模組內的方法了。

1
2
3
class Dog
include spinning
end

如果建立一個狗類別也想要使用只要引入他也可以有這項能力。

類別和模組的差別?

在 Ruby 裡,「類別」的上層類別就是「模組」
可以進入 irb 透過 supercalss 來看到 Class 的上層就是 Module

1
2
3.1.2 :001 > Class.superclass
=> Module

比較兩者的差異:
在 irb 中類別及模組後面加上.instance_methods,就可以查到所有內部具有的實體方法,將兩者相減可以知道差異

1
2
3.1.2 :002 > Class.instance_methods - Module.instance_methods
=> [:allocate, :superclass, :subclasses, :new]

下層的 Class 類別,比 Module 類別多了 4 個方法,其中 allocate 及 new 造就以下的差異:

  • 模組沒辦法 new 一個新的實體出來 (new)。
  • 模組沒辦法繼承別的模組 (allocate)。

如何選擇用類別繼承還是模組?

如果你發現你要使用功能,可能在很多不同體系的類別裡都會用得到,那你可以考慮把功能寫在模組裡,需要的時候再 include 進來。


  1. 為你自己學 Ruby on Rails
  2. [Ruby] 物件(object)、類別(class)和模組(module)