メソッド

概要

Rubyではすべての操作をメソッドで行います。 ここではメソッドについて説明します。

メソッドとは

Rubyでは全てのデータがオブジェクトでした。 それと同じように、Rubyではすべての操作がメソッドによって行われます。

メソッドはオブジェクトに定義されているもので、そのオブジェクトを操作するために使われます。

例えば、2.4 オブジェクトで出てきた.classは「オブジェクトのクラスを返す」というメソッドです。 練習問題で出てきた.to_sは「オブジェクトを文字列オブジェクトに変換する」メソッドです。

メソッドの呼び出し

メソッドを使うことを、「メソッドの呼び出し」といいます。

メソッドは次のようにして呼び出します。

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

先頭にオブジェクトがあり、その右に.(ピリオド、ドット)と呼び出すメソッド名を書きます。 メソッドに別のデータを渡すときは、括弧をつけてカンマ区切りで渡します。 このメソッドに渡すデータのことを引数といいます。 また、メソッドが呼ばれるオブジェクトのことをレシーバとも言います。

例えば演習問題(1)で出てきたFile.read("sample1.txt")だと、レシーバはFile、メソッド名はread、引数は"sample1.txt"になります。

また、引数の括弧を省略することもできます。次の2つは同じ意味です。

File.read("sample1.txt")
File.read "sample1.txt"

引数がない場合も同様です。

"1234".to_i()
"1234".to_i

レシーバの種類

レシーバには大きく分けて3つあります。

  • インスタンス(普通のオブジェクト)
  • クラス
  • なし

それぞれについて説明します。

インスタンスメソッド

"Hello, world!"という文字列オブジェクトや、1234のような数値オブジェクトのような普通のオブジェクトのことをインスタンスといいます。

インスタンスはクラスを元に生成されます。 これまでで説明したオブジェクトという言葉はインスタンスという言葉とほぼ等しいと思ってください。

"Hello, world!"のようなオブジェクトをインスタンスという言葉を使って正確に説明すると、「"Hello, world!"はStringクラスのインスタンス」というような言い方になります。 まあ「"Hello, world"の種類はStringクラス」の言葉を変えただけですね。

インスタンス(オブジェクト)をレシーバにとして呼び出すメソッドのことをインスタンスメソッドといいます。

例えば、次のようなものがあります。

irb(main):001:0> 1234.class
=> Fixnum
irb(main):002:0> 1234.5.to_i
=> 1234
irb(main):003:0> "dog, cat, rabbit".split(",")
=> ["dog", " cat", " rabbit"]

上から

  • 整数値オブジェクト(Fixnumインスタンス)がレシーバのclassメソッド
  • 小数値オブジェクト(Floatインスタンス)がレシーバのto_iメソッド
  • 文字列オブジェクト(Stringインスタンス)がレシーバのsplitメソッド

となっています。

それぞれのオブジェクトによってどのようなメソッドが使えるかは決まっています。 例えば、Fixnumインスタンスに対してsplitメソッドは使えません。

irb(main):008:0> 12345.split
NoMethodError: undefined method `split' for 12345:Fixnum

クラスメソッド

インスタンスメソッドの他にクラスをレシーバとするメソッドもあります。 そのようなメソッドをクラスメソッドといいます。

クラスはオブジェクト(インスタンス)の種類のことでした。 そのため、クラスメソッドにはそのクラスのインスタンスを生成するようなメソッドが多いです。

例えば、次のようなものがあります。

irb(main):001:0> String.new("Hello, world!")
=> "Hello, world!"
irb(main):002:0> Time.now
=> 2015-10-14 10:58:27 +0900
irb(main):003:0> File.read("sample1.txt")
=> "# はじめての...(省略)

上から、

  • Stringクラスのnewメソッドで新しい文字列オブジェクトを生成
  • Timeクラスのnowメソッドで現在時刻の時刻オブジェクトを生成
  • Fileクラスのreadメソッドでファイルの内容から文字列オブジェクトを生成

となっています。 クラスは必ずStringTimeFileのように最初が大文字のアルファベットで始まります。

クラスメソッドもクラスによってどのようなメソッドが使えるかは決まっています。

関数的メソッド

Rubyではレシーバを省略できる場合もあります。 そのようなメソッドを関数的メソッドといいます。

例えば、今まで使った中だとputsprintが関数的メソッドになります。

irb(main):001:0> puts "Hello, world!"
Hello, world!
=> nil

このputsもメソッドで、実はKernelという特別なクラス1のクラスメソッドになっています。 このようにレシーバを省略するとKernelクラスのクラスメソッドとして呼び出されます。

なので、putsは次のように明示的にKernelクラスのクラスメソッドとして呼び出すこともできます。

irb(main):004:0> Kernel.puts "Hello, world!"
Hello, world!
=> nil

メソッドの定義

メソッドはプログラマが自分で定義することもできます。 メソッドの定義は次のようにします。

def メソッド名(仮引数1, 仮引数2, ..., 仮引数n)
  処理
end

仮引数は引数を受取るための変数です。 処理は複数行になっても構いません。

例えば、受け取った引数に対して挨拶するメソッドを作ってみます。

def hello(name)
  puts "Hello, " + name
end

# 使うときは普通のメソッドと同じように呼び出す
hello("Ruby")

このプログラムを実行すると、「Hello, Ruby」と表示されます。

メソッドの返り値

メソッドは必ずなにか値(オブジェクト)を返します。 メソッドが返す値を返り値といいます。

返り値はreturnというキーワードで明示的に指定することができます。

例えば、与えられた数値を2倍した数値を返すメソッドを作ってみます。

def double(number)
  doubled = number * 2
  return doubled
end

puts double(10)

このプログラムを実行すると、「20」と表示されます。

メソッド内でreturnを使うと、その後の処理は無視されます。 例えば次のようにしても、putsは無視されてしまいます。

def double(number)
  doubled = number * 2
  return doubled
  puts "無視されます"
end

また、returnを省略することもできます。 その場合、メソッド内で最後に評価した式の値がメソッドの返り値になります。

def double(number)
  number * 2
end

この例だと、メソッド内で最後に評価したのがnumber * 2なので、引数を2倍した値がdoubleメソッドの返り値になります。

演算子風メソッド

Rubyでは全ての操作がメソッドです。 これまで何度か1 + 2のように普通の数式っぽい式が出てきましたが、これも実はメソッドを呼び出しています。 こういった演算子風のメソッド呼び出しは、+-のような特別なメソッド名にだけに許可されています。

1 + 2の場合、1オブジェクトの+メソッドを2を引数として呼び出しています。 なので次の2つは同じ意味になります。

irb(main):001:0> 1 + 2
=> 3
irb(main):002:0> 1.+(2)
=> 3

練習問題

(1) メソッドを使ってみる

irbで今まで使ったメソッドを使ってください。 インスタンスメソッド、クラスメソッド、関数的メソッドをそれぞれ1つずつ以上は使ってください。

(2) 演算子風メソッド

irbで演算子風メソッドを、演算子形式の呼び出しと普通のメソッド形式の呼び出しの両方で実行してください。

最低でも以下の6つはやってみてください。

  • 数値 + 数値
  • 数値 * 数値
  • 数値 - 数値
  • 数値 / 数値
  • 文字列 + 文字列
  • 文字列 * 数値

例 (文字列 + 文字列):

irb(main):002:0> "Hello" + ", world!"
=> "Hello, world!"
irb(main):001:0> "Hello".+(", world!")
=> "Hello, world!"

(3) 挨拶メソッドの定義

以下の処理を行うhello_method.rbというプログラムを作成してください。

  • 受け取った引数に対しての挨拶を画面に出力するhelloメソッドを定義する
  • helloメソッドをそれぞれ違う引数で3回以上呼び出す

また、実行して結果が正しいか確認してください。

(4) 2倍メソッドの定義

以下の処理を行うdouble_method.rbというプログラムを作成してください。

  • 受け取った引数を2倍した値を返すdoubleメソッドを定義する
  • doubleメソッドをそれぞれ違う引数で3回以上呼び出して返り値を画面に表示する

また、実行して結果が正しいか確認してください。

(5) 足し算メソッドの定義

以下の処理を行うsum_method.rbというプログラムを作成してください。

  • 3つの引数を受取り、全てを足した和を返すsumメソッドを定義する
  • sumメソッドをそれぞれ違う引数で3回以上呼び出して返り値を画面に表示する

また、実行して結果が正しいか確認してください。

(6) インスタンスメソッドの定義

特定のオブジェクトに新しくインスタンスメソッドを定義することもできます。 次のようにして定義します。

def オブジェクト.メソッド名(仮引数1, 仮引数2, ..., 仮引数n)
  処理
end

例えば、ある文字列オブジェクトに新しくprint_myselfというインスタンスメソッドを定義するには次のようにします。

str = "Hello, world!"

def str.print_myself
  puts "私は #{self} です。"
end

str.print_myself

インスタンスメソッドの中では、selfでそのオブジェクト自身を参照することができます。

上記のようなprint_myselfを定義して実行するinstance_method.rbというプログラムを作成してください。 また、実行して結果が正しいか確認してください。

(7) 自己紹介メソッド

以下の処理を行うintroduce_method.rbというプログラムを作成してください。

  • 名前や年齢などを受け取って自己紹介するintroduceメソッドを定義する
  • 自分と隣の人のプロフィールを引数としてintroduceメソッドを呼び出す

また、実行して結果が正しいか確認してください。

1. Kernelは正確にはクラスではなくモジュールといいます。