Rubyの言語仕様2

メソッド

これまで、画面に出力するputsメソッドや、キーボードからの入力を文字列に変換するgetsメソッド、 また行末の改行を削除するchompメソッドや、文字列を整数に変換するto_iメソッドを使ってきました。

ここでは、メソッドについてもう少し詳しく説明します。

メソッドとは

メソッドとは、おおまかに言うと、関数のようなものです。

数学の関数を説明すると、

という関数fが定義されているとするとします。

この関数fに対し、x=2y=3とすると、関数f13を返します。

Rubyのメソッドも同様に、(引数として)渡したオブジェクト(値など)を使って、あらかじめ定義された処理を行い、結果としてオブジェクト(値など)を返したり、オブジェクトに影響を与えたりします。

一般的なメソッド呼び出しの書き方は、以下のようになります。

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

オブジェクトについては、オブジェクト指向で説明します。

また、メソッドには、以下のような特徴があります。

  1. メソッドはオブジェクト内で定義されている。
  2. オブジェクトは、省略できる場合がある。
  3. メソッド名は、半角英小文字または_から始める。途中に半角数字を含めても良い。
  4. 引数の丸カッコ()は省略できる。
  5. 引数が必要かどうかは、メソッドの定義による。引数を必要としないメソッドもある。
  6. メソッドは、オブジェクト(値など)を返す。

Rubyのメソッドは、Ruby内部で数多く定義されています。しかし、すべてのメソッドを覚えている人は、(ほとんど)いませんし、覚える必要もありません。 プログラミングでは、こういう処理をしたいと思った時に、まずは、Rubyのリファレンスや参考書籍などを見たり、インターネットで検索します。

見つかれば、そのメソッドの使い方を調べて、分かりやすく効率的な書き方を考えて、自分のプログラムに書きます。

慣れてくると、だいたいあのメソッドを使えばできそうとか、あの辺りを調べる(検索する)と出てきそうなどと、当たりをつけることができるので、より早くプログラムが書けるようになります。

言ってしまえば、プログラミングは覚えるより慣れろです(筆者の個人的な意見)。

メソッドの定義

メソッドは、プログラム上で独自のメソッドを定義することができます。特に、繰り返し使う場合は有効です。

メソッド定義の書き方は、以下のようになります。

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

最後に処理した(行の)結果が、自動的に戻り値となります。明示的に記述したい場合は、return文を使います。

上記の関数fをRubyで定義すると、以下のようになります。

def f(x, y)
  # Rubyでのべき乗演算子は**です。
  return x**2 + y**2 # returnはなくても正しく動作します。
end

定義したfメソッドを使ったプログラムの例は、以下のようになります。

number1 = gets.chomp.to_i
number2 = gets.chomp.to_i
result = f(number1, number2)
puts "結果:#{result}"

プログラムを実行すると、以下のようになります。

2
3
結果:13
Method

プログラムに直接メソッド定義を書くと、メソッド呼び出しのオブジェクト.は省略できます。

後半で説明するクラスの定義内でメソッドを定義すると、

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

という書き方になります。

クラスのオブジェクトについては、オブジェクト指向で説明します。

配列(Array)

配列は、データを順番に入れておく箱のようなものです。角括弧[]を使って表現します。

以下が、配列の例です。

[] # 空の配列
[5, 394, 3.14, -4] # 数値(整数、実数混ぜても可)
["バナナ", "りんご", "パイナップル", "梨"] # 文字列
["アメリカ", 327750000, "日本", 125810000, "インド", 1334220000] # ミックスも可

データの位置には番号(インデックス)が振ってあります。配列の先頭が0で、以下1, 2, 3, ・・・と増えていきます。

特定のデータを取得するには、角括弧[]を使ってインデックスを指定します。

配列のデータの取得、入れ替えの例です。

ary = ["バナナ", "りんご", "パイナップル", "梨"] 
puts ary[1] # りんごと表示
ary[1] = "アップル" # 2番目のデータを書き換え
puts ary[1] # アップルと表示

配列を扱うメソッドや構文はいくつもあります。以下は、追加と削除の例です。

ary << "キウイ" # 末尾にキウイを追加
puts ary[4] # キウイと表示
ary.delete_at(2) # パイナップルを削除
puts ary[3] # キウイと表示

配列には、先頭から順番にデータを取り出す便利なメソッドeachがあります。

eachメソッドの書き方は、以下のようになります。

配列.each do |引数|
  引数を使った処理
end

配列の先頭からデータを一つずつ引数に入れ、doendの間の行で、引数を使った処理を行います。

以下が、eachメソッドを使った例です。

populations = ["アメリカ", 327750000, "日本", 125810000, "インド", 1334220000]

gusu = true
populations.each do |data|
  if gusu
    print "#{data}の人口:"
    gusu = false
  else
    puts "#{data}人"
    gusu = true
  end
end

プログラムを実行すると、以下のようになります。

アメリカの人口:327750000人
日本の人口:125810000人
インドの人口:1334220000人
Array

ハッシュ(Hash)

ハッシュは、データをキーバリューのペアで入れておく箱のようなものです。波括弧{}を使って表現します。

ペアは、キー => バリューや、キー: バリューで表します。

以下が、ハッシュの例です。

{} # 空のハッシュ
{0 => "バナナ", 1 => "りんご", 2 => "パイナップル", 3 => "梨"} # キーが整数、バリューが文字列の例
{"アメリカ" => 327750000, "日本" => 125810000, "インド" => 1334220000} # キーが文字列、バリューが整数の例
{jp: "日本", kr: "韓国", cn: "中国", fr: "フランス", de: "ドイツ"} # キー:表記を使った例

ハッシュは、主にキーを角括弧[]を使って指定して、バリューの値を取得します。

ハッシュのバリューの取得、入れ替えの例です。

hash = {0 => "バナナ", 1 => "りんご", 2 => "パイナップル", 3 => "梨"} 
puts hash[1] # りんごと表示
hash[1] = "アップル" # キー1のバリューを書き換え
puts hash[1] # アップルと表示

ハッシュを扱うメソッドや構文はいくつもあります。以下は、追加と削除の例です。

hash[4] = "キウイ" # キー4にキウイを追加
puts hash[4] # キウイと表示
hash.delete(2) # キー2とバリューパイナップルのペアを削除
puts hash[2] # キー2がないので何も表示されない

ハッシュにも、キーとバリューのペアデータを一つずつ取り出す便利なメソッドeachがあります。

eachメソッドの書き方は、以下のようになります。

ハッシュ.each do |引数1(キーに対応), 引数2(バリューに対応)|
  引数1、引数2を使った処理
end

ハッシュの先頭からキーとバリューのペアデータを一つずつ取り出し、引数1キーを、引数2バリューを入れ、doendの間の行で、引数1引数2を使った処理を行います。

以下が、eachメソッドを使った例です。

populations = {"アメリカ" => 327750000, "日本" => 125810000, "インド" => 1334220000}

populations.each do |data_key, data_value|
  puts "#{data_key}の人口:#{data_value}人"
end

プログラムを実行すると、以下のようになります。

アメリカの人口:327750000人
日本の人口:125810000人
インドの人口:1334220000人
Hash

データをどう扱うかによって、配列とハッシュをうまく使い分けます。

オブジェクト指向

Rubyは、オブジェクト指向言語です。オブジェクト指向の概念は、かなり難しく、理解するにはしっかり学ぶ必要があります。

ここでは、簡単な説明と、Rubyでのオブジェクト指向の使い方について説明します。

すぐに理解できなくても大丈夫です。クラス(後述)を使っていくうちに、次第に理解できます。

オブジェクト指向とは

オブジェクト(Object)を日本語に訳すと物体対象です。これでは、意味が分かりません。プログラミングでのオブジェクトとはどういう意味でしょうか。

  • Wikipedia プログラミングにおいて、プログラム上の手続きの対象を抽象化する概念。

  • e-Words1 ソフトウェアが扱おうとしている現実世界に存在する物理的あるいは抽象的な実体を、属性(データ)と操作(メソッド)の集合としてモデル化し、コンピュータ上に再現したもの。

概念を簡単に図解すると以下のようなイメージです。

Object

では、実際に現実のものにこの抽象的な概念が当てはまるでしょうか。実物のテレビで考えてみます。

Television HW

当てはまりそうですね。それでは、テレビアプリの場合はどうでしょうか。

Television SW

当てはまりますね。よく見ると、実物でもアプリでも抽象化すると、同じデータやメソッドを持ちそうです。

あたかも、もの=機械を設計し、設計図どおりに(大量)生産するかのように、プログラムで、もの=アプリを設計し、設計図どおりに(大量)生産する書き方をオブジェクト指向と言います。

Rubyには、オブジェクト指向でプログラムを書くための、仕組みが備わっています。

オブジェクト指向プログラミング言語は、継承ポリモルフィズムカプセル化の特徴があります。
とても難しいので、ここでは省略します。

クラス(Class)とは

クラス(Class)とは、オブジェクトの設計書と言えます。具体的には、オブジェクトが扱うデータとメソッド(処理)の定義書です。

Rubyの内部では、多数のメソッドが定義されていると言いました。 より厳密に言えば、多くのクラスが定義され、その中に多くのメソッドが定義されているということになります。

これまで言及しませんでしたが、Rubyでは、文字列や数値はオブジェクトです。つまり、クラスとして定義されています。配列やハッシュも同様です。

Class

Rubyリファレンスマニュアルには、多くのクラスが記載してあります。

Rubyには、組み込みライブラリ標準添付ライブラリがあります。組み込みライブラリは、使用頻度が多い重要なクラスが定義されています。標準添付ライブラリは、必要な時に(明示的に)呼び出して使うクラスが定義されています。

クラスの定義

メソッドと同様に、プログラム上で独自のクラスを定義することができます。

クラス定義の書き方はいろいろあり、また複雑ですが、基本的には以下のようになります。

def クラス名
  def initialize(引数1, 引数2, ・・・, 引数n)
    変数の初期化など
  end

  def メソッドA(引数A1, 引数A2, ・・・, 引数An)
    メソッド1の処理
  end

  def メソッドB(引数B1, 引数B2, ・・・, 引数Bn)
    メソッド2の処理
  end

  ・・・
end

テレビの設計書から、テレビの実体を製造するように、プログラムでも、クラス定義からクラスの実体を生成します。

クラスの実体をオブジェクトと呼びますが、オブジェクトは広い意味で使われることもあるので、このクラスの実体を特にインスタンスと呼びます。

一般的なクラスの実体を生成する書き方は、以下のようになります。

クラス名.new(引数1, 引数2, ・・・・, 引数n)

クラスには、以下のような特徴があります。

  1. クラス名は、半角英大文字から始める。
  2. newメソッドが呼ばれると、自動的にクラス定義内のinitializeメソッドが実行される。
  3. 必要なければinitializeメソッドを定義しなくてよい。また、引数は必須ではない。
  4. 変数名は、半角英小文字または_から始める。途中に半角数字を含めても良い。
  5. 同じクラスのメソッド内で、共通の変数を使うことができる。その場合、先頭に@を付ける必要がある。

クラスを使ったプログラム

クラスの使用例として、数当てゲームのプログラムをクラス定義に適用してみます。

# プログラム名:数当てゲーム(number-guessing-game2.rb)
# 説明:ランダム生成した整数を予測して当てるゲーム

# クラス定義
Class NumberGuessingGame
  # newメソッド実行時に呼ばれるメソッド
  def initialize()
    @seikai = rand(1..100)
    @hazure = true
    super
  end

  # ゲームを開始して終了まで面倒を見るメソッド
  def start
    self.description
    self.game
    self.finish
  end

  # 説明の表示
  def description
    puts "数当てゲーム"
    puts "1から100までの整数をランダム生成します。その数を当ててください。"
  end

  # ゲーム本体
  def game
    while @hazure
      print "正解と思う整数を入力してください:"
      nyuryoku = gets.chomp.to_i # nyuryoku変数はこのメソッド内のみで使うため、先頭に@は必要ない。
      hyouka(nyuryoku)
    end
  end

  # 入力値の判断
  def hyouka(input)
    if @seikai < input
      puts "正解は入力値より小さいです。"
    elsif @seikai > input
      puts "正解は入力値より大きいです。"
    else
      @hazure = false
    end
  end

  # 正解した時の表示
  def finish
    puts "正解です。"
  end
end

# クラスのインスタンス化と実行
game = NumberGuessingGame.new
game.start

説明してないことも多く含まれています。分からないところは、調べてみてください。

クラス定義やクラスの使い方については、まだまだいろいろあります。

  1. 出典の内容が変更されましたが、以前掲載されていた内容をここでは使用しています。 

更新日: