Rails - alias & alias_mehtod 的用法和區別
Rails alias & alias_mehtod 的用法和區別
最近在工作上看到類似像這樣的寫法:
# Under instance project
class Order
# alias Common method :foo to call :foo under instance project
alias_method :foo_common, :foo
def foo(order)
res = foo_common(order)
calc_attr_price(order, res.attr) if res.attr.present?
res
end
end
簡單介紹我們的程式架構是由一個共用的 Common 程式為基礎,根據不同的專案需求另外擴充 Instance module。
在這個例子中,為了因應不同國家的條件計算附加費用,
於是透過 alias_method,在 Instance module 的 :foo 方法中,先呼叫位於 Common 的 :foo 方法(這邊化名為 :foo_common)之後,再接著執行 :calculate_tax_price 計算附加費用並回傳結果。
也就是說,只有在 Instance module 中呼叫 :foo 將會另外再加計附加費用, 如此便可以在不改動原本 Common 程式碼的情況下得到我們所期望的最終金額。

結構示意圖
我該用 alias 或 alias_method ?
在 Ruby 中還有一個關鍵字:alias 常讓人搞不清楚他們適合怎樣的使用情境,
這裡先從使用方法來看看:
- alias 使用方法
class User
def full_name
puts "Steven Chang"
end
alias name full_name
end
User.new.name #=> Steven Chang
- alias_method 使用方法
class User
def full_name
puts "Steven Chang"
end
# 在參數之間需要加上 ","
alias_method :name, :full_name
end
User.new.name #=> Steven Chang
alias_method 可以接受 string 或 symbol 作為參數傳入,參數之間需要加上逗號分隔。
繼承的類和作用域
再來觀察兩者作用的範圍有何不同?
首先是 alias_method:
class User
def full_name
puts "Steven Chang"
end
def self.set_alias
alias_method :name, :full_name
end
end
class Developer < User
def full_name
puts "碼農"
end
set_alias
end
Developer.new.name #=> 碼農
可以看到,在 Developer 類別呼叫 :full_name 的別名 :name,會取得 Developer 中設定的 “碼農”,使用 alias 的情況則有些不同:
class User
def full_name
puts "Steven Chang"
end
def self.set_alias
# 在這邊改用了 alias 關鍵字
alias :name :full_name
end
end
class Developer < User
def full_name
puts "碼農"
end
set_alias
end
Developer.new.name #=> Steven Chang
當我們改用 alias 時,對 Developer 類別呼叫 :name 方法會取得它所繼承的 User 類別中 :full_name 設定的值,而非原本預期寫在 Developer 類別裡的 “碼農”。
這就是 alias 作為 keyword 關鍵字的語彙範疇(lexical scope)特性,alias 所看到的 self 指向程式在分析讀取階段當下的 self,它只認當下所處的 scope,在這個例子就是 User 類別之中;
而 alias_method 則作用在動態範疇(dynamic scope),它看到的 self 指向程式執行當下(run time)的 self,也就是執行 Developer.new.name 的 :name 方法指向的 Developer 實體。
小結
- 兩者都可以重新命名一個方法。
在子類別重寫(override)父類別的方法時,可以用來呼叫舊方法。
- 區別:
alias:- Keyword used by Ruby.
- 會作用於關鍵字所在的類別。
- 參數可以是方法名稱或符號,不含逗號。
alias_method:- Method defined in Module class.
- 是一個模組方法,必要時也可以擴充功能,使用上比較有彈性。
- 參數可以是陣列或符號,參數之間必須加逗號。