什麼是 模組 (module)
昨天介紹完class後,今天來談談模組(module),不知道你們小時候有沒有玩過RPG類型的遊戲,如果有 你可以想像一下,當你的角色想要學習更厲害的招式技能時,可能會需要有技能包才能學習,模組就像是技能包這樣。
在Ruby裡,類別跟模組是很相似的,我們來試試看
puts Class.superclass
#=> Module
當我們想找class的上層時,會得到 Module 這個類別,「類別」是「模組」的後代,類別根本就是繼承自模組來的。
那差別是什麼?
# 前、後代的實體方法差異:
p Class.instance_methods - Module.instance_methods
#=>[:allocate, :new, :superclass]
allocate 跟 new 跟產生實體(instance)有關,superclass 跟繼承有關。
也就是說,類別比模組多了可以「產生實體」的能力以及「繼承」的能力。
整理一下上面的重點
1.模組沒辦法 new 一個新的實體出來。
2.模組沒辦法繼承別的模組。
那要怎麼使用模組呢?
在Ruby定義模組, 使用的是 module
module Flyable #定義模組跟類別一樣,開頭都要大寫
def fly
puts "I can fly!"
end
end
寫好模組後 要套用到類別裡,使用include
class Bird
include Flyable
end
kitty = Bird.new
kitty.fly # => I can fly!
這樣Bird就有飛行的方法囉
如何透過 include prepen 和 extend 來引入 Module。
include
加入模組最常用到的是 include。
當一個 class 使用 include 引入 Module 的時候,會將 Module 內的 method 增加為自己的 instance method:
module Commentable
def comment
'I love comments!'
end
end
class Post
include Commentable
end
class Quote
include Commentable
end
Post.new.comment # => "I love comments!"
Quote.new.comment # => "I love comments!"
Post.ancestors # => [Post, Commentable, Object, Kernel, BasicObject]
Quote.ancestors # => [Quote, Commentable, Object, Kernel, BasicObject]
prepend
而如果使用prepend 來引入 Module, 則會放在繼承練的下方
module Commentable
def comment
'I love comments!'
end
end
class Post
prepend Commentable
def comment
'Post and comment'
end
end
Post.new.comment # => "I love comments!"
Post.ancestors # => [Commentable, Post, Object, Kernel, BasicObject]
extend
extend 則是會將 Module 引入到 class 的 singleton class 上方。
也就是說 Module 的 method 會變成 class mehtod
module Commentable
def comment
'I love comments!'
end
end
class Post
extend Commentable
end
Post.comment # => "I love comments!"
Post.singleton_class.ancestors # => [#<Class:Post>, Commentable, ...]
參考資料:
Ruby 語法放大鏡之「類別跟模組有什麼不一樣?」
Ruby 的繼承鍊 (2) — Module 的 include、prepend 和 extend
Modules in Ruby: Part I