[鼠年全馬鐵人挑戰22]為自己學Ruby on Rails [05- 類別vs實體及一推變數們]

SANDRA
:: SANDRA ::菜菜工程師X全馬挑戰
6 min readSep 12, 2020

|前言|

我們都知道Ruby是一個物件導向很測底的語言吧!常常在Ruby裡面看到很多人在講類別及實體的差別,以及Ruby常用的一些變數用法,那類別(class )其實就是模具,我們丟相同的材料進去,做出來的東西照理來說都一樣,而實體 (instance)就是那個模具做出來的東西。

1 |類別 (class)

class 類別的名字(通常是常數,字首大寫英文字母)
#...
end
  1. 類別名通常是常數,字首為大寫英文字母
  2. 有了 類別之後,就可以用這個類別的 new 方法來產生實體
  3. 如果兩個物件都是用同個類別做出來的,就可以有相同的方法
class Puppy
def eat(food)
puts "#{food} 太美味了吧~"
end
end
Cindy = Puppy.new
Cindy.eat "牛奶~" #=> 印出「牛奶~太美味了吧~」

Molly = Puppy.new
Molly.eat "罐罐~" #=> 印出「罐罐~太美味了吧~」

上方用Puppy類別做了兩個不同的實體 CindyMolly,這兩個物件因為都是用 Puppy 類別做出來的,所以都有 eat 方法

常數 (Constant)
1. 大寫英文開頭
2. 覆寫會報警告,但是還是會被覆蓋
3. 任何model、class、module的名稱都是常數

2 |初始化 (initialize)

class 類別的名字
def initialize(參數1,參數2)
#...
end
end
  1. 想要透過 new 方法傳參數進來,在類別裡面就用initialize 的方法來接收傳進來的參數
  2. initialize 常見的手法是會把參數傳進來給內部的實體變數(instance variable)
class Hello
def initialize(greet, name)
@greet = greet
@name = name
end

def morning
puts "#{@greet}, my name is #{@name}"
end
end

Sandra = Hello.new("Good morning", "Sandra~")
Sandra.morning # => Good morning, my name is Sandra~

先用實體變數做一個盒子@greet@name,之後參數就可以往裡面丟,然後設定呼叫時傳入的參數,就可以在預設的地方抓出對的參數#{@greet}、#{@name}

initialize 永遠是 private 的,只會被 new 方法呼叫

3 |實體變數(instance variable)

  1. 前面加了 @ 符號的變數,沒有預設值
  2. 每個實體變數之間互不相影響
  3. 可以在同一個class的各種method之間互相傳遞
  4. 最常用的地方是 Controller 與 View 之間的溝通
  5. Ruby 的實體變數沒辦法直接從外部取用,要取用實體變數,需要另外定義的方法
class PostsController < ApplicationController
def index
@posts = Post.all # 取得所有的 Post 資料
end
end

=>這是一個Controller 設定取得所有Post的資料

class Hello
def initialize(greet, name)
@greet = greet
@name = name
end

def morning
puts "#{@greet}, my name is #{@name}"
end
def name
@name
end
def name=(new_name)
@name = new_name
end
end

Sandra = Hello.new("Good morning", "Sandra~")
Sandra.morning # => Good morning, my name is Sandra~
Sandra.name = "Ivy"
puts Sandra.name # => 新名字就會變成Ivy

=>這裡定義的 name 以及 name= 方法(等號也是方法的一部份)就是負責回傳及設定 @name 這個實體變數

class Hello
attr_accessor :name #讀取 + 設定

def initialize(greet, name)
@greet = greet
@name = name
end
def morning
puts "#{@greet}, my name is #{@name}"
end
end

=>可使用 attr_accessor 改寫成這樣,即「讀取 + 設定」的方法

4 |實體方法(instance method)VS 類別方法(class method)

  1. 字面翻譯就是,作用在實體上的方法,以及作用在類別上的方法(一整個有講跟沒講一樣,直接看範例吧~)
Sandra = Hello.new("Good morning", "Sandra~")
Sandra.morning

=> morning 作用在Sandra 上面,所以morning 是實體方法

class PostsController < ApplicationController
def index
@posts = Post.all # 取得所有的 Post 資料
end
end

=>這裡的 all 是直接作用在 Post 這個「類別」上,所以就稱它為類別方法

2. 類別方法有幾種寫法,其中一種比較簡單的,就是在前面加上 self

class Cat
def self.all
# ...
end
end
#當一個類別裡面有很多類別方法的時候,不需要在每個前面加上self
class Cat
class << self
def all
# ...
end
end
end

5 |類別變數

  1. 前面加了 @@ 符號
  2. 存在於類別裡面的變數
@@name
@@count

6 | 全域變數 (global variable)

  1. 前面加了$符號的變數
  2. 盡量少用,因為全域變數能夠編寫於任何地方,所以相對危險
  3. 指定一個描述性名稱 (descriptive name),以防之後重複使用
  4. 優點就是能夠追蹤,每當變數的值改變後,你都能夠指出呼叫出
trace_var :$x, Proc.new { puts “$x is now #{$x}” }$x = 5 # =>$x is now 5

7 | 區域變數 (local variable)

  1. 非大寫字母開頭的名字或 _開頭
  2. 不需要先宣告,沒有預設值,Ruby會自動指定一個nil值給他
  3. 有效範圍:class、module、def或do end {}
  4. 沒辦法跨method使用
def create_lv
local_var #=> "區域變數無法在方法外被提取"
@instance_var #=> "可以被任意提取"
end
puts local_var #=> error:undefined local variable
puts @instance_var #=> get @instance_var in create_lv

|後記|

今天把類別及實體的一些觀念釐清後,更能清楚了解Ruby在寫的時候要注意的寫法,另外變數們也有很多觀念,例如$、@@、@、區域變數、常數(區域變數、常數須先宣告,其餘不用),讓我可以提升自己在看code時的速度~~

--

--