iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 3
1
Modern Web

30天修煉Ruby面試精選30題系列 第 3

Day03 - Ruby比一比: Module的include與extend

前情提要

第一天裡,我們很激昂地用Ruby的類別物件方法,寫了開賽宣言!
第二天裡,我們比較了方法與模組,比的過程中,發現模組多了包含(inclusion)與延伸(extension)。

超級比一比 類別 Class 模組 Module
父類別 superclass 模組 Module 物件 Object
繼承 inheritance 可繼承 不可繼承
包含 inclusion 不可被包含 可被包含*
延伸 extension 不可延伸 可被延伸*
實例化 instantiation 可被實例化(instantiated) 不可被實例化

所以在第三天的文章裡,進一步研究module中的inclusionextension是必須的!


Ruby經典面試題目 #03

包含與延伸有什麼不同? What's the Difference Between Include and Extend?

還記得我們昨天舉的例子:網路圖書館(模組)有很多知識(方法)讓我們取用(include),讓你與我都能夠突破先天(繼承)的限制,變成更加聰明靈活的IT人。

module Library
  def IThelp
    p "I'm learning from others' IT articles on IThelp Website!"
  end
end

class EveryoneLearnsRuby
  def initialize(name)
    @name = name
  end
  include Library
end

Ting = EveryoneLearnsRuby.new("Ting")
Ting.IThelp
You = EveryoneLearnsRuby.new("You")
You. IThlep

當然,使用類別(class)繼承也有它的好處,

例如:在已有的功能基礎上,再追加擴展本身已有功能。
(龍生龍、鳳生鳳;老鼠生的兒子會打洞!)

或是以相同名稱的方法,重新定義,產生不同的效果。
(王老先生有塊地,那王小弟長大後可以把王老先生的那塊地拿去蓋民宿。)

但模組(module)的include就像開外掛一樣,讓我們可以在這個星球上學會更多技能。

為了比較includeextend,我們把圖書館模組來稍加改寫:

module Library
  def IThelp
    p "IThelp helps me!"
  end
end

class NewbieLearnsRuby
  include Library
end

NewbieLearnsRuby.new.IThelp
#IThelp helps me!

NewbieLearnsRuby.IThelp
#NoMethodError

如果我們把NewbieLearnsRuby.new.IThelp誤寫成NewbieLearnsRuby.IThelp,就會NoMethodError出現錯誤。

undefined method `IThelp' for NewbieLearnsRuby:Class (NoMethodError)

奇怪,為什麼會這樣呢?

我們回到改寫前的圖書館例子:我先宣告(new)一個新物件You,
讓「You」這個變數名字指向EveryoneLearnsRuby.new("You")

You = EveryoneLearnsRuby.new("You")
You.IThlep

所以剛剛的NewbieLearnsRuby.new.IThelp其實是以下的簡化:

You = NewbieLearnsRuby.new
You.IThelp
# [NewbieLearnsRuby.new].IThelp [中括號內的變數就是You!]

這就是我們為什麼不能漏掉.new的原因。

那,如果改寫成extend的程式碼,會變成如何呢?

module Library
  def IThelp
    p "IThelp helps me!"
  end
end

class NewbieLearnsRuby
  include Library
end

class ExtendRuby
  extend Library
end

NewbieLearnsRuby.new.IThelp
# IThelp helps me!

ExtendRuby.IThelp
# IThelp helps me!

由以上可知,include代表Newbie類別學Ruby時需要new一個新的物件實體,然後才能使用方法
extend不用,在Extend類別中使用它,可以直接把方法拿過來用。

ExtendRuby.IThelp
# IThelp helps me!

ExtendRuby.new.IThelp
# NoMethodError

同樣的,想進一步了解為什麼輸入ExtendRuby.new.IThelp也是NoMethodError。接下來我們要拿關鍵字 the difference between include and extend in ruby去請教Google大神:

Now that we know the difference between an instance method and a class method, let's cover the difference between include and extend in regards to modules. Include is for adding methods to an instance of a class and extend is for adding class methods. 出處

為了抽絲剝繭這段話的含義,這裡的實體方法instance method類別方法class method將會成為我們下一篇文章的重點囉!

第三天感想

寫文章真的很有趣!當我寫出NewbieLearnsRuby這種名稱的class,就彷彿自己像寫一本武俠小說一樣,盡情地創造準備開始練功的新人物、新主角。

身為新手工程師,螢幕是我們的畫布~鍵盤上的各個中英文字、數值、符號就是我們的顏料,
享受寫程式 + 寫文章的過程,願我們都可以在人生畫布上,揮灑、創造自己的新世界!

https://ithelp.ithome.com.tw/upload/images/20181009/20111177sVotTnShhj.png

Ref:


上一篇
Day02 - Ruby比一比: Module模組與Class類別
下一篇
Day04 - 玩弄Ruby的方法: instance method與class method
系列文
30天修煉Ruby面試精選30題31

尚未有邦友留言

立即登入留言