iT邦幫忙

DAY 24
1

Ruby女孩:10萬.times { puts "為什麼?" }系列 第 24

Ruby女孩(24):模組是不生孩子的!模組與類別差異及mixin介紹

  • 分享至 

  • xImage
  •  

今天來談談模組(module),是一個很容易跟類別(class)搞混的名稱!我們先下一行指令來看看這兩者之間的關係:

Class.superclass
=> Module

是的,類別是模組的小孩模組能做的類別都能做,那,根據昨天的繼承概念,類別這小孩比他老爸模組還擴充了哪些方法呢?

Class.instance_methods - Module.instance_methods
=> [:allocate, :new, :superclass]

我們用這行指令來做簡單的陣列減法運算XD,看看類別的實體方法比模組的實體方法多了哪些!蝦米啊!只多了三個方法,而且由這三個方法可以明確發現類別跟模組的最大差異:

1. 模組不可以做出實體物件,所以不能使用.allocate與.new[註1]。

2. 模組之間也不能被繼承,所有的模組之間都是獨立的,不生孩子(不能建立子類別)!

[註1].allocate是什麼?
看個例子理解一下:

class Test
  def initialize(test=5566)
    @test = test
  end
end

aaa = Test.new
=> #<Test:0x007fc9228e1ff0 @test=5566>

bbb = Test.allocate
=> #<Test:0x007fc923c928d8>

當我們幫Test類別建造實體物件時...
1. 使用.new,會分配空間給新物件,並調用類別中的initialize方法。
2. 使用.allocate,會分配空間給新物件,但不會調用initialize方法。
[參考資料]http://apidock.com/ruby/Class/allocate

阿嬤:『安捏喔,那模組要怎麼使用呢?』

※ 模組的mixin用法

『如果一個模組定義的是實體方法,而不是類別方法,這些實體方法可以混進(mix in)其他類別。...欲將一個模組混進一個類別,可以使用include。』(p.260)

module Trytry
  def who_am_i
    "我屬於#{self.class}"
  end
end

class RubyGirl
  include Trytry
end

annie = RubyGirl.new.who_am_i
=> "我屬於RubyGirl"

仔細看看上方的程式碼,我在Trytry模組中定義了一個實體方法,然後在RubyGirl類別中include Trytry,結果當我替RubyGirl類別製作出新的實體物件時,這個物件就享有Trytry模組中的實體方法了!

其實之前在Ruby女孩17所提到的次序比較時,我們就有偷偷使用過一個模組的mixin用法,我們將Comparable模組引用進一個類別中,讓那個類別也能有次序比較的方法:

class RubyGirl
  include Comparable
  attr_accessor :age
  def initialize(age)
    @age = age
  end
  def <=> (the_other_one)
    self.age <=> the_other_one.age
  end
end

annie = RubyGirl.new(25)
=> #<RubyGirl:0x007fb7091169b8 @age=25>

linda = RubyGirl.new(18)
=> #<RubyGirl:0x007fb709112b38 @age=18>

annie > linda
=> true

linda <=> annie
=> -1

要注意!
1. mixin所使用的include,只能include模組,不能include類別。
2. 類別可以include模組,模組也可以include模組。

要混入模組的方法除了『include』,也可以使用『extend』。如果是在類別中寫『extend 模組』,該模組的實體方法將轉變成類別的類別方法:

module Trytry
  def who_am_i
    "我屬於#{self.class}"
  end
end

class RubyGirl
  extend Trytry
end

RubyGirl.who_am_i
=> "我屬於Class"

注意到了嗎?這次改成extend Trytry後,不需要.new產生實體物件就可以使用who_am_i,就是因為現在who_am_i已經變成RubyGirl的類別方法了。

模組當然不止mixin使用,書中還有提到可作為命名空間之用,但這個部分自己尚未理解清楚,就先不要打上來誤人子弟了XD

=================================================

24天!

“You got this. Make it happen.”- Danielle LaPorte


上一篇
Ruby女孩(23):Ruby中的繼承者們!有錢真好(誤)
下一篇
Ruby女孩(25):來認識方法的定義與解除!
系列文
Ruby女孩:10萬.times { puts "為什麼?" }30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言