方法參數¶
這是方法參數和呼叫引數的正式規格。
方法定義的組成¶
方法定義包含:
- 必要和選用的位置參數
- 一個可選的 splat 參數,其名稱可以為空
- 必要和選用的具名參數
- 一個可選的雙 splat 參數
例如:
def foo(
# These are positional parameters:
x, y, z = 1,
# This is the splat parameter:
*args,
# These are the named parameters:
a, b, c = 2,
# This is the double splat parameter:
**options
)
end
它們每一個都是可選的,因此方法可以不用雙 splat、不用 splat、不用具名參數,也不用位置參數。
方法呼叫的組成¶
方法呼叫也有一些組成部分
foo(
# These are positional arguments
1, 2,
# These are named arguments
a: 1, b: 2
)
此外,呼叫引數可以有 splat (*
) 或雙 splat (**
)。Splat 會將 元組展開為位置引數,而雙 splat 會將 具名元組展開為具名引數。允許多個引數 splat 和雙 splat。
呼叫引數如何與方法參數匹配¶
當呼叫方法時,將呼叫引數與方法參數匹配的演算法是:
- 首先,位置呼叫引數會與位置方法參數匹配。這些引數的數量必須至少為沒有預設值的位置參數數量。如果存在一個帶有名稱的 splat 參數(沒有名稱的情況如下所述),則允許更多位置引數,並且它們會被捕獲為元組。位置引數永遠不會匹配超過 splat 參數。
- 然後,具名引數會按名稱與方法中的任何參數匹配(它可以在 splat 參數之前或之後)。如果參數已經被位置引數填滿,則會發生錯誤。
- 額外的具名引數會放入雙 splat 方法參數中,作為 具名元組,如果該參數存在,否則會發生錯誤。
當 splat 參數沒有名稱時,表示不能再傳遞更多位置引數,並且任何後續的參數都必須作為具名引數傳遞。例如:
# Only one positional argument allowed, y must be passed as a named argument
def foo(x, *, y)
end
foo 1 # Error, missing argument: y
foo 1, 2 # Error: wrong number of arguments (given 2, expected 1)
foo 1, y: 10 # OK
但是,即使 splat 參數有名稱,後續的參數也必須作為具名引數傳遞
# One or more positional argument allowed, y must be passed as a named argument
def foo(x, *args, y)
end
foo 1 # Error, missing argument: y
foo 1, 2 # Error: missing argument; y
foo 1, 2, 3 # Error: missing argument: y
foo 1, y: 10 # OK
foo 1, 2, 3, y: 4 # OK
也可以通過在開頭放置星號,使方法只接收具名引數(並列出它們)
# A method with two required named parameters: x and y
def foo(*, x, y)
end
foo # Error: missing arguments: x, y
foo x: 1 # Error: missing argument: y
foo x: 1, y: 2 # OK
星號之後的參數也可以有預設值。這表示:它們必須作為具名引數傳遞,但不是必須的(因此:選用的具名參數)
# x is a required named parameter, y is an optional named parameter
def foo(*, x, y = 2)
end
foo # Error: missing argument: x
foo x: 1 # OK, y is 2
foo x: 1, y: 3 # OK, y is 3
由於 splat 參數之後的參數(沒有預設值)必須按名稱傳遞,因此兩個具有不同必要具名參數的方法會發生重載
def foo(*, x)
puts "Passed with x: #{x}"
end
def foo(*, y)
puts "Passed with y: #{y}"
end
foo x: 1 # => Passed with x: 1
foo y: 2 # => Passed with y: 2
位置參數始終可以按名稱匹配
def foo(x, *, y)
end
foo 1, y: 2 # OK
foo y: 2, x: 3 # OK
外部名稱¶
可以為方法參數指定一個外部名稱。外部名稱是在將引數作為具名引數傳遞時使用的名稱,而內部名稱是在方法定義內部引用參數時使用的名稱
def foo(external_name internal_name)
# here we use internal_name
end
foo external_name: 1
這涵蓋了兩種使用案例。
第一種使用案例是將關鍵字作為具名參數
def plan(begin begin_time, end end_time)
puts "Planning between #{begin_time} and #{end_time}"
end
plan begin: Time.local, end: 2.days.from_now
第二種使用案例是使方法參數在方法主體內部更具可讀性
def increment(value, by)
# OK, but reads odd
value + by
end
def increment(value, by amount)
# Better
value + amount
end