はじめに
この記事は書籍「プロを目指す人のためのRuby入門」に掲載できなかったトピックを著者自らが紹介するアドベントカレンダーの2日目です。
本文に出てくる章番号や項番号は書籍の中で使われている番号です。
今回はメソッドの引数をアスタリスク1文字にするイディオムを紹介します。
必要な前提知識
「プロを目指す人のためのRuby入門」の第7章まで読み終わっていること。
メソッドの引数をアスタリスク1文字にするイディオム
4.4.7項でも説明したとおり、メソッド定義で引数の前に*
を使うとその引数が可変長引数になります。
def greeting(*names)
"#{names.join('と')}、こんにちは!"
end
greeting('田中さん') #=> "田中さん、こんにちは!"
greeting('田中さん', '鈴木さん') #=> "田中さんと鈴木さん、こんにちは!"
greeting('田中さん', '鈴木さん', '佐藤さん') #=> "田中さんと鈴木さんと佐藤さん、こんにちは!"
可変長引数は次のように引数名を省略することもできます。
def greeting(*)
# 中身はいったん空にする
end
greeting('田中さん') #=> nil
greeting('田中さん', '鈴木さん') #=> nil
greeting('田中さん', '鈴木さん', '佐藤さん') #=> nil
さて、このままだと何もメリットがないように見えますが、以下のような条件が揃った場合にアスタリスク1文字だけの可変長引数が利用されることがあります。
- サブクラスが
super
を使ってスーパークラスの同名メソッドを呼び出す - 渡された引数は全部そのままスーパークラスに渡す
- サブクラスのメソッド内では引数を利用しない
たとえば次のようなコードです。
class Product
attr_reader :name, :price
def initialize(name, price)
@name = name
@price = price
end
end
class DVD < Product
# 明示的にname, priceという引数を書く代わりに、*だけで済ませる
def initialize(*)
# 渡された引数を全部そのままスーパークラスに渡す
super
# サブクラスで必要な初期化処理を書く
end
end
dvd = DVD.new('A great movie', 1000)
dvd.name #=> "A great movie"
dvd.price #=> 1000
サブクラス側の実装は可変長引数なのでいくつでも引数を渡せますが、スーパークラス側はそうではないため、結果的に引数の数は2個に制限されます。
DVD.new('A great movie', 1000, 'foo')
#=> ArgumentError: wrong number of arguments (given 3, expected 2)
super
の使い方については「7.6.5 superでスーパークラスのメソッドを呼び出す」の項で説明したので、忘れた方はもう一度読み直してください。
少しトリッキーなので、初心者のうちはわざわざこのような書き方を真似する必要はありません。
ですが、gemのコードを読んでいると、ときどきアスタリスク1文字の引数が登場することがあるので、知っておくとコードリーディングの際に役立つ場合があります。
次回予告
次回はローカル変数の宣言と代入の関係について説明します。