メソッドはオブジェクトに行ってほしい動作を伝えるために使われます。
例えば下のようなスクリプトがあったとします。
1 2 |
a = "object".length p a |
6
「length」メソッドは文字数を返すので、戻り値は「object」の6文字となります。
このとき「”object”」は「length」メソッドから文字数を返すようにメッセージを受け取り、戻り値として「6」を返しています。今回の場合で「Stringオブジェクト」はメソッドからメッセージを受け取っているので「レシーバ」とも言います。
Contents
メソッドは3種類に分類されます
「レシーバ」の種類によって「メソッド」は下記の3つに分類されます。
- インスタンスメソッド
- クラスメソッド
- 関数的メソッド
オブジェクトがどのようなものであるか説明した型枠、オブジェクトの設計図のようなものです。
クラスの型枠から作られたもの、設計図に基いて作られているようなイメージです。
インスタンスメソッド
インスタンスメソッドとは「レシーバ」がインスタンス(オブジェクト)自体であった場合のメソッドのことを言います。
1 |
p "5".to_i |
5
上記の例では「Stringオブジェクト」が「to_iメソッド」のレシーバとなっています。「レシーバ」が「オブジェクト」となっているのでこれは「インスタンスメソッド」となります。
クラスメソッド
クラスメソッドとは「レシーバ」がクラスそのものであった場合のメソッドのことを言います。
1 |
p Array.new |
[]
上記の例では「new」で新しく「Array」クラスのインスタンスを作成しています(新たな配列を作っています)。今回の場合は「レシーバ」が「クラス」なのでこれを「クラスメソッド」といいます。
関数的メソッド
関数的メソッドとは「レシーバ」自体がない(省略されている)場合のメソッドのことを言います。
1 |
puts("hello") |
hello
上記の場合は「hello」という文字列が出力されることになります。この場合では「puts」メソッドだけで「レシーバ」がないので、このようなメソッドは関数的メソッドと呼ばれています。
メソッドを定義する
メソッドを定義する場合の書き方は一般的には下記のように記述します。
1 2 3 |
def メソッド名(引数) 処理内容 end |
メソッド名のみを定義すればそのメソッドを「関数的メソッド」として呼び出すことができます。下のように「”こんにちは”」と表示するメソッドがあったとします。
1 2 3 4 |
def hello puts "こんにちは" end hello |
こんにちは
これが1番簡単なメソッドと呼び出しではないかと思います。1~3行でメソッドを定義し、4行目の「hello」で関数的メソッドとして呼び出しています。次にこのメソッドに引数(パラメータ)を渡してみましょう。
メソッドの定義で引数を設定
1 2 3 4 |
def hello(name) puts "こんにちは#{name}" end hello("やぎちゃん") |
こんにちはやぎちゃん
今回の場合は引数として文字列「”やぎちゃん”」が変数「name」に代入されています。その結果、「こんにちは」と「やぎちゃん」が文字列として出力(puts)されています。引数を設定している場合でメソッド呼び出し時にパラメータ(引数)を設定していない場合はエラーが出ます。
1 2 3 4 |
def hello(name) puts "こんにちは#{name}" end hello |
上記のようなファイル「method.rb」を実行した場合は、下のように表示されます。
C:\Users>method.rb C:/Users/method.rb:5:in hello': wrong number of arguments (given 0, expected 1) (ArgumentError) from C:/Users/method.rb:8:in <main>'
呼び出した際の引数は0(無し)なのに、1つ引数が期待されていますよ~といった感じのエラーが表示されています。
引数にデフォルト値を設定
このようなエラーを避けるには引数にデフォルトの値を設定すればOKです。書き方は下のような感じです。
1 2 3 4 |
def hello(name = "やぎちゃん") puts "こんにちは#{name}" end hello |
こんにちはやぎちゃん
呼び出しの際に引数を渡さなかった場合は自動的にその文字列が変数に代入されることになります。
戻り値を指定する
定義するメソッドの中に「return」と入れると戻り値を指定することができます。
1 2 3 4 5 |
def hello(name = "やぎちゃん") puts "こんにちは#{name}" return "OK" end p hello |
こんにちはやぎちゃん "OK"
通常ならputsを行った場合は1番最後に「nil」が返ってきますが、今回は戻り値を文字列としたため「”OK”」と最後に返ってきます。また、「return」は省略することができ、省略した場合は最後に得られる値が戻り値となります。
引数を配列として受け取る
引数の数を決めていない場合や、残ってしまう場合は「*」(アスタリスク)を変数の前に付けることで、残った値を配列として、格納することができます。
1 2 3 4 5 6 7 8 9 |
def num(*a, b) return a, b end p num(1, 2, 3, 4, 5) def num2(*c) return c end p num2(6, 7, 8, 9, 10) |
[[1, 2, 3, 4], 5] [6, 7, 8, 9, 10]
配列を展開して代入
今度は逆に渡す前の引数が配列だった場合をみていきましょう。
1 2 3 4 5 |
def num(x, y, z) puts "x=#{x}, y=#{y}, z=#{z}" end ary = [1, 2, 3] num(*ary) |
x=1, y=2, z=3
配列の前に「*」をつけると自動的に展開されて初めから順番にそれぞれの変数に代入されていることがわかります。
キーワード引数
キーワード引数を設定すると、引数名と引数の値自体をセットとして呼び出すことができます。先程までのメソッドの呼び出し方は順番どおりとなっていましたが、引数名を指定して引数の値を代入できるので順番どおりでなくても大丈夫です。
1 2 3 4 5 |
def num(x: 0, y: 0, z: 0) puts "x=#{x}, y=#{y}, z=#{z}" end num(y: 1, z: 2, x: 3) num(y: 1, z: 2) |
x=3, y=1, z=2 x=0, y=1, z=2
また、5行目のようにxの値を引数として渡していない場合でも、すでにデフォルト値「x: 0」が決まっているのでエラーは発生しません。下記のように「引数名:」で値を記述しない場合はデフォルト値は設定されませんが、引数を渡さなかった場合にはエラーは発生します。
1 2 3 4 5 |
def num(x:, y: 0, z: 0) puts "x=#{x}, y=#{y}, z=#{z}" end num(y: 1, z: 2) num(x: 0, y: 1, z: 2, a: 3) |
C:/Users/method.rb:1:in num': missing keyword: x (ArgumentError) from C:/Users/method.rb:4:in <main>'
なお、5行目のように定義していない引数名(今回の場合はa: 3)の値を渡してもエラーが発生します。
余った値をハッシュオブジェクトとして代入
定義していない引数名をエラーを出さずに渡すこともでき、その場合は「**変数名」と記述します。
1 2 3 4 |
def num(x:, y: 0, z: 0, **arg) puts "x=#{x}, y=#{y}, z=#{z}, arg=#{arg}" end num(x: 0, y: 1, z: 2, a: 3, b: 4) |
x=0, y=1, z=2, arg={:a=>3, :b=>4}
実行結果をみると引数名として定義していないaとbは変数「arg」にハッシュで代入されていることがわかりますね。
ハッシュオブジェクトを引数として渡す
さっきとは逆にハッシュオブジェクトをキーワード引数として渡すこともできます。
1 2 3 4 5 6 |
def num(x: 0, y: 0, z: 0) puts "x=#{x}, y=#{y}, z=#{z}" end num({x: 0, y: 1, z: 2}) num({y: 1, z: 2, x: 3}) num({y: 1, z: 2,}) |
x=0, y=1, z=2 x=3, y=1, z=2 x=0, y=1, z=2
ハッシュを引数として代入した場合も大体今までと処理と同じような実行結果が得られていますね。
ハッシュをまとめて渡す
メソッドの定義の際に変数だけ設定していればハッシュの情報をまとめて渡すことができます。
1 2 3 4 5 |
def num(a) puts "a=#{a}" end num({x: 0, y: 1, z: 2}) num(x: 0, y: 1, z: 2) |
a={:x=>0, :y=>1, :z=>2} a={:x=>0, :y=>1, :z=>2}
ハッシュで渡す場合は、({x: 0, y: 1, z: 2})の{}の部分は省略することもできます。省略してみるとキーワード引数として渡しているのと非常に似た形になりますね。。このハッシュを引数に渡す方法がもともと実装されており、後からキーワード引数が作られたらしいです。
コメントを残す