こんにちは、かつコーチです。
「メソッドの基本的な定義はできるけど、引数の種類が多くて混乱する」。
Rubyを学び始めた方から、こうした悩みをよく聞きます。
今回は、defによるメソッド定義の基本から、デフォルト引数・可変長引数・キーワード引数まで、順番に解説します。
読み終える頃には、目的に応じて適切な引数の形を選べるようになります。
基本のメソッド定義
defでメソッドを定義する
Rubyでは、defからendまでの範囲でメソッドを定義します。
def greet(name)
"こんにちは、#{name}さん"
end
puts greet("かつコーチ") # => こんにちは、かつコーチさん
Rubyのメソッドは、最後に評価された式の値が自動的に戻り値になります。
returnを書かなくても、greetメソッドの最後の行(文字列)がそのまま返されます。
もちろん、明示的にreturnを書くこともできます。
def greet(name)
return "こんにちは、#{name}さん"
end
途中で処理を打ち切りたい場合は、returnを使うと分かりやすくなります。
引数の数が違うと呼び出せない
Rubyのメソッドは、定義した引数の数と、呼び出し時に渡す引数の数が一致していないとエラーになります。
def greet(name)
"こんにちは、#{name}さん"
end
greet
このコードを実行すると、次のようなエラーが発生します。
ArgumentError (wrong number of arguments (given 0, expected 1))
「引数を1つ期待していたのに、0個しか渡されていない」という意味のエラーです。
このエラーへの対処として使えるのが、次に紹介するデフォルト引数です。
デフォルト引数・可変長引数・キーワード引数の使い方
デフォルト引数で省略を許可する
デフォルト引数とは、「引数が渡されなかった場合に使われる初期値」を設定できる仕組みです。
def greet(name = "ゲスト")
"こんにちは、#{name}さん"
end
puts greet("かつコーチ") # => こんにちは、かつコーチさん
puts greet # => こんにちは、ゲストさん
name = "ゲスト"と書いておくことで、引数を省略してもArgumentErrorにならず、デフォルト値が使われます。
「よく使う値は決まっているけど、たまに変更したい」という場面で重宝します。
可変長引数(*args)で任意の数の値を受け取る
可変長引数とは、「いくつ渡されるか分からない引数」をまとめて受け取る仕組みです。
変数名の前に*を付けることで定義できます。
def total(*numbers)
numbers.reduce(0) { |sum, n| sum + n }
end
puts total(1, 2, 3) # => 6
puts total(1, 2, 3, 4, 5) # => 15
*numbersと書くと、渡された引数がすべてnumbersという配列にまとめられます。
引数の数が事前に決まっていない、合計計算や集計処理でよく使われる形です。
キーワード引数で意図を明確にする
キーワード引数とは、「引数名: 値」の形で渡す引数のことです。
def introduce(name:, age: 20)
"#{name}さん(#{age}歳)です"
end
puts introduce(name: "かつコーチ", age: 35) # => かつコーチさん(35歳)です
puts introduce(name: "かつコーチ") # => かつコーチさん(20歳)です
name:のようにコロンだけを付けたものは必須のキーワード引数、age: 20のように初期値を付けたものは省略可能なキーワード引数です。
キーワード引数の最大のメリットは、呼び出し側で引数の意味が一目で分かることです。
# 通常の引数だと、何番目が何を表すか分かりにくい
def introduce(name, age)
"#{name}さん(#{age}歳)です"
end
introduce("かつコーチ", 35) # 35が年齢だと呼び出し側からは推測しにくい
# キーワード引数なら意図が明確
introduce(name: "かつコーチ", age: 35) # ageが年齢だと一目で分かる
引数が3つ以上になるメソッドでは、キーワード引数を使うことを検討するとよいでしょう。
よくあるつまずきポイント・エラー対処
引数の順序を間違えてエラーになる
Rubyでは、通常の引数・デフォルト引数・可変長引数・キーワード引数を混在させる場合、書ける順序が決まっています。
# ❌Before:可変長引数の後にデフォルト引数を置いてSyntaxErrorになる
def sample(*args, greeting = "こんにちは")
puts greeting
end
私は最初にこのルールを知らず、SyntaxErrorの原因が分からず数分固まってしまった経験があります。
Rubyのエラーメッセージは、原因の行を的確に指摘してくれるとは限らないため、慣れないうちは戸惑いやすいポイントです。
# ✅After:通常の引数 → デフォルト引数 → 可変長引数 → キーワード引数の順に並べる
def sample(name, greeting = "こんにちは", *others, age:)
puts "#{greeting}、#{name}さん(#{age}歳)"
puts "その他: #{others.join(', ')}" unless others.empty?
end
sample("かつコーチ", age: 35)
sample("かつコーチ", "やあ", "追加情報1", "追加情報2", age: 35)
エラーが出たときは、まず引数の並び順が正しいかを確認する習慣をつけておくとよいでしょう。
キーワード引数のハッシュとの混同でハマる
Ruby 2.7以前のコードや古い記事を参考にすると、キーワード引数とハッシュの扱いが混在していて混乱することがあります。
# ❌Before:ハッシュのつもりで渡すと、キーワード引数と食い違うことがある
def introduce(name:, age:)
"#{name}さん(#{age}歳)"
end
options = { name: "かつコーチ", age: 35 }
introduce(options) # ArgumentError(Ruby 3系ではハッシュとキーワード引数は別物)
Ruby 3系では、キーワード引数とハッシュ引数が明確に分離されているため、ハッシュをそのまま渡すとエラーになります。
# ✅After:ハッシュを展開してキーワード引数として渡す
def introduce(name:, age:)
"#{name}さん(#{age}歳)"
end
options = { name: "かつコーチ", age: 35 }
puts introduce(**options) # => かつコーチさん(35歳)
**optionsのように**を2つ付けると、ハッシュをキーワード引数として展開して渡せます。
古いRubyの記事を参考にするときは、バージョンによる仕様の違いに注意しましょう。
応用・一歩先の使い方
ダブルスプラット(**)でキーワード引数もまとめて受け取る
可変長引数に*を使ったように、キーワード引数をまとめて受け取りたい場合は**を使います。
def profile(**options)
options.each do |key, value|
puts "#{key}: #{value}"
end
end
profile(name: "かつコーチ", age: 35, job: "エンジニア")
# => name: かつコーチ
# => age: 35
# => job: エンジニア
**optionsと書くと、渡されたキーワード引数がすべてoptionsというハッシュにまとめられます。
「オプション的な設定値をまとめて受け取りたい」というメソッドでよく使われる形です。
引数の組み合わせを実務でどう使うか
実務では、これらの引数を組み合わせて、柔軟なメソッドを設計することがよくあります。
def create_user(name, role: "member", **extra_options)
user = { name: name, role: role }
user.merge!(extra_options) unless extra_options.empty?
user
end
p create_user("かつコーチ")
# => {:name=>"かつコーチ", :role=>"member"}
p create_user("かつコーチ", role: "admin", department: "開発部")
# => {:name=>"かつコーチ", :role=>"admin", :department=>"開発部"}
必須の情報(name)は通常の引数に、よく使う設定(role)はデフォルト引数に、それ以外の任意項目は**extra_optionsにまとめる。
こうした設計にしておくと、後から項目が増えてもメソッドの呼び出し側を大きく変えずに済みます。
まとめ
この記事のポイント
- Rubyのメソッドは最後に評価した式が自動的に戻り値になる
- デフォルト引数(
name = "ゲスト")は引数の省略を許可する - 可変長引数(
*args)は任意の数の引数を配列として受け取る - キーワード引数(
name:)は呼び出し側で意図が明確になる - 引数の並び順(通常 → デフォルト → 可変長 → キーワード)にはルールがある
- ダブルスプラット(
**options)でキーワード引数をハッシュとしてまとめて受け取れる
次に読むべき記事
引数の次は、Rubyらしい書き方の代表格である「ブロックとyieldの使い方」を読んでみてください。
メソッドとブロックを組み合わせることで、より柔軟な処理が書けるようになります。