どぼじょのIT学習ブログ

高専卒土木女子がIT業界を目指してお勉強。

Ruby入門 part7

Ruby入門続けていきます〜!本日はメソッドについてのお勉強です。

目次

1.メソッド

1-1. 学習の前置き

まず、Rubyをはじめとするオブジェクト指向プログラミング言語では、クラスやメソッドという言葉が使われます。
今までの学習でもたびたび出てきたので、なんとなく概念はわかるかもしれませんが、ここでちゃんと学習します!
オブジェクト指向というのは文字列や数値、配列など様々なオブジェクトが登場します。これらのオブジェクトは、クラスを元に作成しています。
そして作成したオブジェクトから、クラスの中に定義されているメソッドを呼び出します。
わたしの簡単なイメージですが、例えば文字列オブジェクトはStringクラスを元にして作成されています。そしてstringクラスには、printメソッドが定義されているといった感じだと思います🤨
本日はこの「メソッド」についてのお勉強をしていきます!

1-2. Rubyにおけるトップレベ

Rubyではいきなりprint("文字列")というプログラムを書いて文字列オブジェクトを作成できます。
このように、特定のクラス定義の中に記述するのではなく、クラス定義の外側に書くことができます!
このクラス定義の外側部分は「トップレベル」と呼ばれています。
ちなみにこれはRubyの特徴のようですね😳
他のオブジェクト指向プログラミング言語では、先にクラスを定義してから、その中でオブジェクトを作成していくことが多いようです。
はお、トップレベルは何か特定のクラスのメソッドというわけではありません。

Rubyにはselfという式があります。selfは、メソッドの中で実行することで、そのメソッドを実行しているオブジェクトを参照することができます。
では、ここで厳密にはメソッドではないトップレベルでselfを実行してみます🙂

gist.github.com
to_sは、モジュールやクラスを表す文字列を返してくれます。(必要なのか??と思ってしまいますが、とりあえず付けておきます)
2行目には、そのオブジェクトのクラスを表示させるプログラムを書きました。
結果は以下のとおりです。
f:id:mistyrinth:20181120200927p:plain
selfにより、mainというオブジェクトが返ってきました。更に、mainというオブジェクトはObjectクラスを元にしていることが分かりました🎉

また、トップレベルに定義されたメソッドはKernelモジュールの中に追加されることになっているそうです。
モジュールという言葉が新しく出てきて、いよいよ難易度高い雰囲気がしてきますね😭笑
モジュールについては今後Ruby入門の中で学ぶことになるので、今は「クラスに似ているもの」という解釈でいきます👌

1-3. メソッドの定義と呼び出し

いよいよメソッドの定義の方法を学びます。なんとなくプログラミングの幅が広がる気がしますねー!
以下の書き方でメソッドを定義できます。

def メソッド名(引数1, 引数2, ...)
    実行する処理1
    実行する処理2
end

Rubyでよく見かけるdef、ついに登場です👀
引数の( )は省略できるみたいです。
メソッド名をつけるにあたり、ルールがあります。

  1. 1文字目は英文字(a,b,A,Bなど)かアンダーバー(_)
  2. 2文字目以降は英数文字(a,b,A,B,1,2,など)、アンダーバー(_)

メソッドを呼び出すためには、以下のように書きます。

オブジェクト名.メソッド名(引数1, 引数2, ...)

繰り返しになりますが、メソッドはクラスの中に定義されます。
そして、そのクラスを元にして作成されるオブジェクト(レシーバー)に対して、メソッドを実行します。
そのため、メソッドを呼び出す時には、実行する対象のオブジェクトを指定する必要があります。 ただしトップレベルに定義されたメソッドはオブジェクト名の部分(レシーバー)を省略できます💡 また、引数も省略することができます。その場合、併せて( )も省略できます✨

メソッドの定義付けから呼び出しまで、実際にやってみました!

gist.github.com

実行結果は以下のとおりです。
f:id:mistyrinth:20181120215730p:plain
うまくできました!💪💪💪

1-4. 引数を付けたメソッド呼び出しとデフォルト値

今度は引数を付けて呼び出してみます。
呼び出す時は、以下のように、メソッドに渡したいオブジェクト(引数)を記述します。

メソッド名(引数1, 引数2, ...)

また、呼び出されるメソッドの変数は、受け取るオブジェクト(引数)の数と一致している必要があります。

def メソッド名(変数1, 変数2, ...)
    実行する処理1
    実行する処理2
end

このとき、変数に格納されるのはオブジェクト(引数)のコピーではなく、オブジェクトそのものを格納していることになります👀
配列などを学習した後だと一見ややこしく思えますが、メソッドはオブジェクトに対して「実行するもの」だと思えば、当然のことかなあと思います😊
printメソッドなど具体的に考えるとわかりやすいですね👏

実際にやってみました。

gist.github.com
結果は以下のとおりです😎
f:id:mistyrinth:20181121203045p:plain

先程の説明で「呼び出されるメソッドの変数は、受け取るオブジェクト(引数)の数と一致している必要があります」と書きました。
実際に作ったプログラムを見ると分かりやすいのですが、messagenameという2つの変数があり、それぞれに"こんにちは"と"田中さん"という2つの文字列オブジェクト(引数)が代入されています😶
1番目の引数は1番目の変数へ、2番目の引数は2番目の変数へ、順番に代入されていくイメージが掴めるかと思います。
ここで例えば"こんにちは"しか指定しなかったら、nameは空になってしまいます。このように、変数が空になってしまう場合のデフォルト値を設定できます。

def メソッド名(変数1=デフォルト値1, 変数2=デフォルト値2, ...)
    実行する処理1
    実行する処理2
end

先程のプログラムにデフォルト値を設定してみました🙂

gist.github.com

結果は以下のとおりです。名前を入力しなかったら、デフォルト値が返ってきました✨
f:id:mistyrinth:20181121212701p:plain

なお、呼び出す時にメソッド側の変数よりも多い引数を指定すると、エラーとなります。

1-5. 引数を配列として受け取る

メソッドを呼び出す時、メソッド側の変数よりも多い引数を指定すると、エラーとなると説明しました。
ただし、メソッドの最後の変数にアスタリスク*を付けておくと、エラーにならず、余ったぶんの引数を要素とした配列オブジェクトを受け取ります。
書き方は次の通りです。

def メソッド名(変数1, 変数2, ..., *変数n)
    実行する処理1
    実行する処理2
end

gist.github.com

上記のプログラムで使っている<<は、配列の最後に要素を追加する演算子です。
おそらくですが、allnameという配列にnameが次々と付け足されていっているのだと思います。
結果は以下のとおりです!

f:id:mistyrinth:20181121220713p:plain
allnameに、余った引数(名前)が羅列されていますね😆

1-6. メソッドの戻り値

メソッドを呼び出した時の結果(戻り値)を、メソッドの呼び出し元の変数に返すことができます。

変数 = メソッド名(引数1, 引数2, ...)

メソッド側のreturn文の後ろに記述された式の値が戻り値となります。

def メソッド名(変数1, 変数2, ...,)
    実行する処理1
    実行する処理2

    return 式
end

ちなみに、returnは省略可能です。その場合、メソッド内の最後の式の結果が戻り値となります。
またreturn文の位置は最後である必要はなく、if文の中だったり、メソッド内ならどこにあってもOKです👌
これだけで理解するのはちょっと難しいので、実際にやってみます!

gist.github.com

実行結果は以下のとおりです。
f:id:mistyrinth:20181121231251p:plain

メソッドの実行結果(戻り値)は1つしかありませんが、配列オブジェクトを戻り値にすることもできます😊
その場合、returnの後の「式」の部分に、戻したい要素を含めた配列を書くだけです💡

def メソッド名(変数1, 変数2, ...,)

  実行する処理1   実行する処理2

  return [要素1, 要素2, ...]  end

さらに、一旦戻り値として配列を受け取ってから、配列の要素を取得することもできます🎉
ちょっとテクニカルですが、多重代入の形で戻り値を2つ書いてしまうこともできます!
多重代入についてはこちらの記事の「変数」をご参照ください🙃

実際にやってみます。

gist.github.com

結果は以下のとおりです。
f:id:mistyrinth:20181121234859p:plain

メソッドについては以上です😋