iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 5
0
Modern Web

關於 Ruby on Rails,我想說的是系列 第 5

[Day 5] 類別(class)與模組(module)

  • 分享至 

  • xImage
  •  

類別與模組是 Ruby 物件導向精神的重中之重,第二天有提到,在Ruby 裡面幾乎萬物皆物件

物件(object)是什麼?

物件是承載資料與行為的東西,物件行為就是物件的方法,資料就是昨天提到的變數,被物件帶在身上。

類別(Class)

如果有些物件的行為有相似之處,就可以把它們歸在同一類,也就是同一個類別 class。類別可以說是物件的模子,可以製造一個個具有相似行為的物件,用龍哥的例子來說,類別vs物件就像雞蛋糕模具vs雞蛋糕的關係。

class Animal
  def initialize(name)
  	@name = name
  end
  def shout                #定義物件方法
    p "我的名字是#{@name}"
  end
end

initialize 是類別的初始化方法,注意不要拼錯字喔(我就是拼錯兩次以上的人 (/‵Д′)/~ ╧╧)

上面定義了Animal類別,模具已經準備好,可以來印出兩隻小動物

animal1 = Animal.new('Lucky')
animal2 = Animal.new('Luke')

animal1.shout # => "我的名字是Lucky"
animal2.shout # => "我的名字是Luke"

這樣就產生行為相似,但資料不同的兩個物件。

類別繼承

想在動物類別Animal的基礎上,產生狗類別Dog跟貓類別Cat。就可以使用類別繼承(inherit)來使用已經定義好的Animal方法,加上屬於自己的方法。
![Imgur](https://i.imgur.com/30iiWCO.png =500x)

class Dog < Animal
  def bark
    p "#{@name}會汪汪叫"
  end
end

class Cat < Animal
  def meow
    p "#{@name}會喵喵叫"
  end
end

doggy = Dog.new('風速狗')
kitten = Cat.new('貓老大')

doggy.bark #=> "風速狗會汪汪叫" 
kitten.meow #=> "貓老大會喵喵叫" 

實務上使用Rails開發網站時,會把相同特性放在上層controller,讓下層的controller直接繼承,每個下層controller就不用把相同的行為都寫一次,既讓程式碼簡潔,又符合 Ruby的精神:DRY(Don't Repeat Yourself)
例如所有後台的controller,使用者都應該要登入才能進入,可以先定義一個AdminController,把登入驗證的邏輯寫在這裡,讓其他的controller去繼承他。

類別方法

如果有些方法,整個類別都有特性,跟個別實體身上的資料無關,可以使用類別方法。比方說,所有動物都會呼吸,定義breath方法時前面要加self

class Animal
  def self.breath
    p "呼~"
  end
end

Animal.breath # => "呼~"

模組(Module)

假設有個方法部分類別會用到,我們可以用剛才提過的類別繼承,把這個方法放在上層類別。但這樣做有個缺點,連不需要這些方法的類別都有這個方法。這時候該是模組出場的時候啦。
模組類似我們在RPG遊戲裡的裝備,類別只要裝上了這個模組,就擁有這個模組所有的方法。
比如說,我希望高手類別都配備弓箭模組讓攻擊距離加大

module Arrow
  def send
    p "#{@name}攻擊範圍提升1.5倍"
  end
end

class Master
  include Arrow
  def initialize(name)
    @name = name
  end
end

透過include方法,把Arrow模組加在Master類別上。

來感受一下模組的威力

robin_hood = Master.new('羅賓漢')
robin_hood.send # => "羅賓漢攻擊範圍提升1.5倍"

有沒有覺得模組讓本來的類別能力up了呢?


類別跟模組的差別

看完上面的例子,你或許覺得模組跟類別都可以定義物件方法,到底有什麼差別?
最大的差別有三個
1.class 可以透過內建的new方法來實體化物件,Moduel不行
2.class 可以繼承取得其他class的特性,Module不行
3.Module 有include或exclude方法來擴充class,但class不能被inlcude 進其他class


上一篇
[Day 4]Ruby 常數與變數四兄弟(下)
下一篇
[Day 6] 猴子補丁 Monkey Patch
系列文
關於 Ruby on Rails,我想說的是23
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言