[Ruby] 方法/函式(function / method)
實例方法
##
# 檢驗 object 中是否包含某一 method
# [object].respond_to?(:[method])
# 也可以不加冒號用引號寫 Obj.respond_to?('[method]')
##
Obj.respond_to?(:next)
Obj.class.respond_to?([method]) # 檢驗某個 obj 的 class 是否包含某 class method
defined? (methods) # 註1
# 檢驗 object 是否為 nil
arr.nil? # [object].nil?
# 檢驗物件類型
:hello.is_a? Symbol # true,[object].is_a? String/Integer/Symbol
:hello.class # Symbol,[object].class
##
# 找出某一物件內的方法來源(註2, 註3)
# 也可以不加冒號用引號寫 Obj.method('methodName')
##
Obj.method(:methodName)
類別方法
[Class].methods # 列出物件內的所有方法
資訊
註 1: In Ruby, how do I check if method “foo=()” is defined? @ StackOverflow 註 2: How to find where a method is defined at runtime? @ StackOverflow 註 3: Find where a method is defined
觀念
implicit return(自動回傳)
在 Ruby 中方法如果沒有寫 return
則會自動回傳方法中最後的表達式。
# method 會自動以 string 的格式 return(implicit return)
def add(a, b)
a+b
end
puts add(3, 5) # 8
命名慣例
在 Ruby 中函式(function)就是方法(method),命名的開頭一般是小寫(也可以是 _ 或數字);結尾可以是?(問號,question)或!(驚嘆號,bang,exclamation)或=(等號,equal)。
一般來說(慣例):
- 結尾如果是
!
,執行方式和一般方法沒有差別,但通常用!結尾,表示會有「副作用」,例如,這個方法會改變原本的變數值,同時也表示它會有一個相對應不會改變原本變數值的方法。 - 結尾如果是
?
,這個方法經常會回傳表示 true 或 false 的物件。 - 結尾如果是
=
,表示這個方法是指派方法(assignment method),在 assignment method 中,函式中的回傳值會被忽略,而是自動回傳參數的值。
# bang, exclamation, 驚嘆號:表示有副作用
a = "Hello everyone"
a.upcase # 沒有驚嘆號,不會改變原本變數的值
puts a # "Hello everyone"
a.upcase! # 有驚嘆號,會改變原本變數的值
puts a # "HELLO EVERYONE"
# question mark,問號:表示回傳 Boolean
a = "Hello everyone"
puts a.nil? # false
puts a.empty? # false
# equal,等號,回傳值會被忽略,直接回傳參數值
def a=
return 3
end
puts a= "Hello", 7
建立方法(method)
建立帶有參數的方法
建立一般的方法
def add(a, b)
puts "{#a} + {#b} is {#a+b}"
end
建立帶有參數預設值的方法
方法內可以定義參數預設值,預設值不一定要放在最前面或最後面,但是必須是組在一起的:
def add_values(a = 2, b)
a + b
end
p add_values 3 # 5
def add_values(a, b = 4)
a + b
end
p add_values 3 # 7
為物件直接新增方法
greeting = "Hello "
def greeting.sayhi(name)
puts self + name
end
greeting.sayhi("Mark") # Hello Mark
建立具有具名參數的方法(named parameter, keyword arguments)
在定義 function 的參數時使用 :
可以達到具名參數的作用, [變數名稱]:[變數預設值]
,一旦對應到相同的名稱,就可以直接使用:
# 使用 : 定義具名參數
def select_options(selected = nil, disabled: nil, prompt: nil)
puts prompt # 可以直接取得具名參數的值,'this is prompt'
puts disabled # 可以直接取得具名參數的值,'disabled'
end
# 使用時可以透過 Hash 的方式帶入參數
select_options(1, prompt: 'this is prompt', disabled: 'disabled')
呼叫方法
可省略括號()
<%= link_to '刪除', user, method: :delete, data: { confirm: 'sure?' }, class:'btn' %>
<%= link_to ('刪除', user, method: :delete, data: { confirm: 'sure?' }, class:'btn') % # 括號可以省略
<%= link_to('刪除', user, {method: :delete, data: { confirm: 'sure?' }, class:'btn'}) %>> # 最後一個參數是 hash 時也可省略大括號
最後一個參數如果是 hash 可省略大括號
方法的最後一個參數如果是 hash 的話可以省略大括號。
這是因為如果第一個參數放 hash 的話,它無法辨識那是 block 或是 hash;如果放在中間,它無法辨識那是一個 {age: 18}
,還是 {age: 18, favorite: ruby}
def say_hello_to(name, options = {})
"Hello, #{name}. Your age is #{options[:age]}. Your favorite programming language is #{options[:favorite]}"
end
say_hello_to "Eddie", {age: 18, favorite: 'ruby'}
say_hello_to "Eddie", age: 18, favorite: 'ruby' # 省略大括號
參數解構(decomposition)
#########################
# 陣列解構賦值 ##
#########################
# 可以在參數的地方多包一個括號來解構陣列
def arr_decompo((a, b))
p a: a, b: b
end
arr_decompo([1,2]) # 回傳 {:a=>1, :b=>2}
# 如果參數的地方所給予的陣列元素超過參數數目,則會自動省略
def arr_decompo((a, b))
puts a: a, b: b
end
arr_decompo([1,2,3]) # 回傳 {:a=>1, :b=>2}
# splat arguments:可以使用*來將多餘的陣列元素轉為陣列
def arr_decompo((a, *b))
puts a: a, b: b # 回傳 {:a=>1, :b=>2}
end
arr_decompo([1,2,3]) # 回傳 {:a=>1, :b=>[2, 3]}
特殊情況
# 當定義同樣名稱的方法時 ,原本的方法會被覆蓋(overriding)
puts "3".to_i # 3
class String
def to_i
"6"
end
end
puts "3".to_i # 6
# 當定義同樣名稱的變數和方法時,會以區域變數優先
age = 18
def age
puts 20
end
age # 18(以區域變數優先)
age() # 20
參考資料
- Methods @ Ruby Documentation
- Codecademy
- TreeHouse
- 為你自己學 Ruby on Rails