Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyのメソッド引数を徹底解説!4つの引数タイプの違いと正しい使い分け

ある読者から「キーワード引数はいつ使うべきか」という意見を求めるメールをいただいたことがあります。

せっかくなので、その回答をRubyのメソッド引数についての完全な記事としてまとめ、多くの方に役立ててもらうことにしました。

Rubyはメソッド引数に関して非常に柔軟な言語です。

あらゆる種類の引数が揃っています

標準的な必須引数から、デフォルト値を持つオプション引数、さらにはキーワード(名前付き)引数まで様々です。

この記事では、これらの引数タイプの違いと、状況に応じてどれを使うべきかを学ぶことができます。

適切な引数を使い分けることで、コードはより読みやすく、扱いやすいものになります。

迷ったら標準的な必須引数を使う

必須引数は、何も指定しない場合にデフォルトで使われる引数です。

例を見てみましょう

def write(file, data, mode)
end

write("cats.txt", "cats are cool!", "w")

必要な数の引数を渡さないと、お馴染みのエラーメッセージが表示されます:

write("shopping_list.txt", "bacon")

ArgumentError: wrong number of arguments (given 2, expected 3)

これは、メソッドに2個の引数を渡したけれど、実際には3個必要だという意味です!

オプション引数で柔軟なメソッドを作る

デフォルト値を指定することで、一部の引数を省略可能にしたい場合があるでしょう。

例えば

def write(file, data, mode = "w")
end

これでwriteを2つの引数で呼び出すこともできるようになりました。その場合、modeはデフォルト値の"w"になります。3つ目の引数を渡せば、デフォルト値を上書きして別の結果を得ることができます。

このデフォルト値のおかげで、呼び出し側の手間が減りながらも、必要に応じて変更する選択肢は残ります。

キーワード引数で明確さを高める

必須引数やデフォルト引数の欠点の一つは、引数の順序に依存することです。

つまり、決まった順序どおりに引数を渡す必要があります。

順序を間違えると

予期しない結果になってしまいます!

例えばwriteメソッドでは、最初にfile、次にdata、最後にmodeを渡す必要があります。

def write(file, data, mode)
end

キーワード引数を使えば、引数の順序を自由に変えられます。

def write(file:, data:, mode: "ascii")
end

これにより、異なる順序でメソッドを呼び出すことができます:

write(data: 123, file: "test.txt")

さらに重要なのは、メソッドを呼び出す際に各引数の意味が一目でわかることです。

筆者自身はキーワード引数を頻繁には使いませんが、メソッド呼び出しの明確さを高めたいときには非常に役立ちます。

例として、Pointクラスを考えてみましょう。

次のように書けます

class Point
  def initialize(x:, y:)
    @x, @y = x, y
  end
end

point = Point.new(x: 10, y: 20)

この書き方なら、2つの数値(10と20)のどちらがxでどちらがyなのか、混乱する余地がありません。

コードを書く上での主な目標の一つは、混乱や誤解をできるだけ避けることです。

キーワード引数がそれに役立つのであれば、遠慮なく使いましょう。

自問してみてください

「キーワード引数を追加すると、このコードは理解しやすくなるか?それとも余計な手間とノイズを増やすだけか?」

キーワード引数のもう一つの利点は、不足している引数を非常に明確に教えてくれることです。

point = Point.new

# missing keywords: x, y

また、キーワード引数は通常の引数と組み合わせることもできます。

Rubyの組み込みメソッドでよく見られる傾向として、新しいバージョンでは新規のオプション引数がキーワード引数として追加されることが挙げられます。

例えば、Ruby 2.4で導入されたFloat#roundKernel#cloneString#linesのキーワード引数がその代表例です。

可変長引数で必要なだけ値を受け取る

任意の個数の値を受け取りたい場合はどうすればよいでしょうか?

そんなときは可変長引数を使います:

def print_all(*args)
end

print_all(1, 2, 3, 4, 5)

これにより、メソッドを任意の個数の引数(0個でも)で呼び出せるようになります。可変長引数は、渡されたすべての値を含む配列になります。

他の種類の引数とも組み合わせることができます。

def print_all(title, *chapters)
end

この場合、1番目の引数がtitleになり、残りはchapters配列に入ります。可変長引数は、必須引数・オプション引数の後ろ、かつキーワード引数の前に置く必要がある点に注意してください。

正しい順序を守る

複数の引数タイプを組み合わせて構文エラーを避けるための、有効な順序は以下の通りです:

required -> optional -> variable -> keyword

すべての引数タイプを使ったメソッドの例

def testing(a, b = 1, *c, d: 1, **x)
  p a,b,c,d,x
end

testing('a', 'b', 'c', 'd', 'e', d: 2, x: 1)

**xは可変長引数のキーワード引数版のようなものです。こちらは配列ではなくハッシュになります。

すべてを受け入れるキャッチオール引数

稀に、次のようなコードを目にすることがあります:

def print_all(*)
end

これは、メソッドがどんな引数でも受け入れるけれど、それを一切使わないという意味です。ブロック内でアンダースコア(_)を使って未使用の引数を示すのと似ています。

実用的な使い方としては、superキーワードとの組み合わせが挙げられます:

class Food
  def nutrition(vitamins, minerals)
    puts vitamins
    puts minerals
  end
end

class Bacon < Food
  def nutrition(*)
    super
  end
end

bacon = Bacon.new

bacon.nutrition("B6", "Iron")

こうしておけば、親クラスFoodのnutritionメソッドの引数リストが変わっても、Bacon側の引数を変更する必要がありません。

まとめ

Rubyの強力なメソッド引数とその使い方について学びました!まずは必須引数から始めて、オプション引数で柔軟性を加え、さらにキーワード引数で明確さを高めるとよいでしょう。

この記事が皆さんのお役に立ち、興味深いものだったなら嬉しいです!

ぜひTwitterでシェアして、より多くの人に届けてください🙂


  1. Rubyのmapメソッド完全ガイド!配列・ハッシュのデータ変換を実例で解説

    Rubyのmapメソッドは、配列(Array)・ハッシュ(Hash)・範囲(Range)といったコレクションに対して使用できる強力なメソッドです。 mapの主な用途は、データの変換です。 例えば、文字列の配列があった場合、すべての文字列を順番に処理して、各文字を大文字に変換することができます。 また、Userオブジェクトのリストがある場合も同様です。 それらを変換して、対応するメールアドレスや電話番号など、Userクラスに定義された任意の属性のリストを作成できます。 それでは、具体的な使い方を見ていきましょう! Ruby mapメソッドの基本構文 mapの構文は次のようになっています。 a

  2. RubyのStructとOpenStructの使い方を徹底解説!値オブジェクトを簡単に作る方法

    Rubyには、関連する属性をまとめて保持する「値オブジェクト」を手軽に作れるStructという組み込みクラスが用意されています。本記事では、Structの基本的な使い方から注意点、そしてOpenStructとの違いまで詳しく解説します。 そもそもStructとは何か? StructはRubyに組み込まれたクラスで、新しいクラスを動的に生成し、値オブジェクト(Value Object)を作成するために使われます。値オブジェクトとは、関連性のある複数の属性をひとまとめにして扱うためのオブジェクトです。 具体例を挙げてみましょう。 2つの座標(xとy)を持つPointというデータを表したい場合、この