本記事ではメソッドを解説します。
前記事のクラスやメソッドの記事で、すでにメソッドは出てきました。
処理をまとめるという点では関数と似ていますが、それ以外はまったく異なります。
本記事で順に解説していきます。
(今後文脈に応じて、インスタンスとオブジェクトの両方を使います。オブジェクトの方がより広義と理解してください)
メソッドとは
メソッドとは、処理をまとめて外部から利用できるようにしたものです。関数と違うのは、メソッドはオブジェクトを操作するためのものです。
レシーバ
まずレシーバについて触れなければいけません。
メソッドを実行するというのは、言い換えればオブジェクトに対してメッセージを送る、といえます。
メッセージパッシングともいいます。ナントカさんコレよろしく、という感じでしょうか。
数値の5を文字列に変えるには、数値の5に変換メソッドto_sというメッセージ送る、ということになります。
数値の5がレシーバで、to_sがやってほしいことであるメッセージです。
(Rubyの世界では、数値はおろかすべてのモノがオブジェクトでしたよね?)
メソッドの呼び出し
単純に呼び出す
オブジェクトに属するメソッドを呼び出す場合は以下のとおりです。
オブジェクト.メソッド名(引数)
引数を取らないメソッドはカッコは不要です。
前記事「【Ruby入門】クラスをコーディング(2) オブジェクト指向」で出てきた以下もそうです。
book = Book.new p book.count
bookというオブジェクトに、countしてくれというメッセージを送っています。countはメソッドです。
関数的メソッド
ではpは何なのか、と思いますよね。
今まで散々でてきたpメソッドやputsメソッドは、レシーバなど意識せず普通に使ってきました。
実はpもputsも、レシーバが不要なメソッドです。
不要というより省略されているといったほうが正しいです。
さらにカッコも省略されているので、メソッドのように見えないのです。
これを関数的メソッドといいます。
本命!プロックつきメソッド
まず、これを見てください。
3.times do |i| puts i end
doからendまでがブロックで、iはブロックパラメータです。
[実行結果]
1 2 3
3.timesは1,2,3と数値を順にブロックパラメータへ送ります。そしてputs iでそれを表示させています。
3というオブジェクトに対してtimesというブロックを送っています。
timesをRubyのマニュアルで調べてみましょう。
以下のように書いています。
self 回だけ繰り返します。 selfが正の整数でない場合は何もしません。またブロックパラメータには 0 から self – 1 までの数値が渡されます。
この説明からも、timesに対してブロックを渡しているのがわかります。
メソッドの分類
メソッドは、大きく分けてインスタンスメソッドとクラスメソッドに分かれます。
順に解説していきます。
インスタンスメソッド
前述の「単純に呼び出す」でも出てきたインスタンスメソッドです。
「【Ruby入門】配列と操作(基本編)」に出てきたsplitを使って解説します。
array = "あああ, いいい, ううう, えええ, おおお".split(",") p array
[実行結果]
["あああ", " いいい", " ううう", " えええ", " おおお"]
これは、“あああ, いいい (省略)”という文字列のレシーバに対してsplitしてください、引数はカンマで、というメッセージを送っています。
文字列はStringクラスのオブジェクトということもお忘れなく。
クラスメソッド
レシーバがインスタンスではなくクラスのメソッドです。
こういうと難しいのですが、単純にインスタンス化しなくとも使える、クラスに紐付いたメソッドと思えば十分です。
特によく見るのはnewでしょうか。
array = Array.new
という記述をいたるトコロで見たかと思います。これもクラスメソッドです。
クラスメソッドを呼び出すには、上記のようにクラス名にドット「.」で可能です。またドットの代わりに::も使えます。
array = Array::new
マニュアル類でよくみる表記 「#」
マニュアル類では、クラス名#メソッド名で表記されている場合があります。
しかしこれはマニュアル上での表現であり、実際にプログラム上で記述するとエラーになりますので注意しましょう。
メソッドを作る
メソッドを作りましょう。
基本形は以下です。
def メソッド名(引数) # 処理 end
クラスの中に定義しなければ、クラスメソッドでもなくインスタンスメソッドでもない、関数的メソッドとなります。
単純に空文字とゼロを渡すメソッドを作りましょう。
def sample(a, b) puts a puts b end sample("", 0)
[実行結果]
(空文字) 0
引数の注意点
引数は、省略した場合の初期値を設定できます。
例えば省略した時には””(空文字)や0(ゼロ)を設定したいときはこうします。
def メソッド名(a = "", b = 0)
引数の数が決まらない場合は、*変数名で対応します。慣例的にargsを使うことが多いです。
以降の解説でも*argsとしますが、基本的には自由です。
def メソッド名(*args)
これで、引数が配列としてまとめて受け取れます。
少なくとも1つ以上必要な場合はこうします。
def メソッド名(変数名, *args)
最初と最後だけ指定して、間はいくつでも構わない場合はこうします。
def メソッド名(変数名1, *args, 変数名2)
キーワード引数
今まで解説してきたメソッドは、順番を合わす必要がありました。
順番をまちがえればエラーになります。
しかしキーワード引数を使うと、引数を指定して渡すことができるのでまちがうことがありません。
商品の数量と単価を渡して、消費税込みの金額を得るメソッドを作ります。
def calctax(number, price) number * price * 1.08 end puts calctax(3, 10000)
[実行結果]
32400.000000000004
小数点以下は消すことができるのですが、本解説の範疇ではないので解説を省略します。
これを、puts calctax(price: 10000, number: 3)としましょう。
def calctax(price: 0, number: 0) number * price * 1.08 end puts calctax(number: 3, price: 10000)
同じ結果が出ます。
引数を逆にしても正常に動くことが確認できました。
戻り値の明記は必須ではない
もう一度、以下をごらんください。(再掲)
def calctax(price: 0, number: 0) number * price * 1.08 end
他言語から来られた方は、return文がないのにお気づきでしょう。
そうです、Rubyでは戻り値を示すreturn文は必須ではありません。
しかし書いたとしてもエラーになりません。
最後に実行された結果が戻り値になる、というルールがありますので、覚えておきましょう。
returnを使うと、以下のようになります。
def calctax(price: 0, number: 0) return number * price * 1.08 end
ただし明示的にreturnを示すこともあります。それは、強制的に終了するときです。
def calctax(price, number) if price < 0 || number < 0 return 0 else return number * price * 1.08 end end
負の数が来たときに、強制的に終了させてみました。
まとめ
本記事ではメソッドについて解説しました。
どれも基本的な内容なので、ご自身で手を動かして確実に理解してくださいね!