iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
Modern Web

Ruby新手村的礦工日記系列 第 16

[ Day 16 ] Ruby 類別 (class)

  • 分享至 

  • xImage
  •  

在 Ruby 中,除了前幾章提到的 "Block" 不是物件以外,其他的東西都是物件。
但那物件又是什麼東西呢?

物件是?

物件(Object) = 狀態(State) + 行為(Behavior)

在生活中,交通工具、動植物、你跟我,只要是看得到、摸得到都可以稱為物件(Object)。
而這些物件都會有狀態跟行為,像是貓有「橘色的毛」、「胖的」、「6歲」等狀態,當然也會有「吃飯」、「走路」、「睡覺」等行為。

類別 (Class) 又是什麼呢?

不曉得大家有沒有吃過雞蛋糕,而雞蛋糕的模具就是個類別 (Class) 的概念,而做出來的雞蛋糕的概念可以叫做實體(Instance)。
所以按照上面的例子,我們可以透過類別(class)組織和產生許多具有相似屬性(attributes)和方法(methods)的物件。

定義類別

在 Ruby 要定義一個累別,使用 class

class MethodName
  # ...
end

在 Ruby 中,慣例來說 Class 會以大駝峰 (CamelCase) 來命名,像是:User、BlogsController ...等。
我們也可以透過 Class.new('argument') 來建立物件。

class Dog
  def eat(food)
    puts "#{food} 好吃!"
  end
end

yui = Dog.new
yui.eat("西莎")   # 印出 西莎 好吃!

lucky = Dog.new
lucky.eat "牛肉"  # 印出 牛肉 好吃!

這邊我用 Dog 類別做了兩個不同的實體,也就是 yuilucky ,這兩個物件因為都是用 Dog 類別做出來的實體,所以都會有 eat 方法。

初始化

現在的雞蛋糕有各式各樣的口味,如果在一開始加入巧克力就可以做出巧克力口味的雞蛋糕。
以上面的例子來看,當使用 new 方法作實體的時候,也可以順便傳參數進去,如下:

class Dog
  def initialize(name, gender)
    @name = name
    @gender = gender
  end

  def say_hi
    puts "hi, my name is #{@name}, I'm #{@gender}." 
  end
end

yui = Dog.new("Yui", "female")
yui.say_hi  # 印出 hi, my name is Yui, I'm female.

若要用 new 方法傳參數進來,在類別裡面必須有個名為 initialize 的方法來接收傳進來的參數。在 initialize 方法裡,常見的手法是會把參數傳進來給內部的實體變數(instance variable)。

實體變數 (instance variable)

Day03 的有提到實體變數,那實體變數是什麼呢?
在 Ruby 裡的實體變數是 @ 開頭的變數,活在每個實體裡的變數,而且每個實體之間互不相影響。
以上面的例子來看, @name@gender 就是實體變數。
在 Rails 專案中,實體變數使用的頻率很高,最常用的地方是 Controller 與 View 之間的溝通,舉例來說:

class BlogsController < ApplicationController
  def index
    @articles = Article.all  # 取得所有的 Article 資料
  end
end

實體方法

實體方法就是作用在實體上的方法
這句話有點像是廢話,舉例來說:

class Dog
  def say_hi(name)
    puts "hello, #{name}"
  end
end
yui = Dog.new
yui.say_hi("Yui") # 印出 hello, Yui

這邊的 say_hi 是作用在 yui 的實體,這稱 say_hi 為實體方法。

類別方法

類別方法指的是可以作用在類別上的方法

class BlogsController < ApplicationController
  def index
    @articles = Article.all  # 取得所有的 Article 資料
  end
end

這邊 all 方法是直接作用在 Article 這個類別上,所以稱為類別方法。

self 建立類別方法

如果不想這麼麻煩,我也可以用 self ,如下:

class Dog
  def self.all
    # ...
  end
end

這時我就可以用 Dog.all 來呼叫方法。
如果你也不喜歡這樣的寫法也可以這樣寫:

class Dog
  class << self
    def all
      # ...
    end
  end
end

實體方法與類別方法

我用下面的例子來總結一下實體方法與類別方法:

class Hello

  def say_instance(name)
    puts "Hi!  我是實體 (#{name}) 方法"
  end

  def self.say_class(name)
    puts "Hello! 我是類別 (#{name}) 方法"
  end

end

greet = Hello.new
greet.say_instance("instance") # Hi!  我是實體 (instance) 方法

Hello.say_class("class")    # Hello! 我是類別 (class) 方法

方法的存取控制

類別的方法存取限制常見的主要有三種: publicprotected 以及 private

  • public: 就是所有的人都可以直接存取。
  • private: 是只有在類別內部才可以存取。
  • protected: 差不多是在這兩者之間,比 private 寬鬆一些,但又沒有 public 那麼自在,protected 在同一個類別內或是同一個 package,或是繼承它的子類別可以自由取用,但如果不是的話則不可存取。

參考資料

  1. 為你自己學 Ruby on Rails
  2. PJCHENder

上一篇
[ Day 15 ] Ruby 中的物件導向程式設計
下一篇
[ Day 17 ] Ruby 中的模組 (Module)
系列文
Ruby新手村的礦工日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言